cry-db 2.5.1 → 2.5.3

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,18 +976,19 @@ 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
919
988
  if (updates === null || updates === void 0 ? void 0 : updates.length) {
920
989
  const updatePromises = updates.map(async ({ _id, _rev: clientRev, update }, idx) => {
921
990
  var _a, _b;
991
+ let processedUpdateForDiagnostics;
922
992
  try {
923
993
  const objectId = Mongo._toId(_id);
924
994
  update = this.replaceIds(update);
@@ -927,9 +997,10 @@ export class Mongo extends Db {
927
997
  const inputUpdate = cloneDeep(update);
928
998
  const processedBase = this._processUpdateObject({ ...update });
929
999
  const processed = this._applyBracketProcessing(processedBase);
1000
+ processedUpdateForDiagnostics = processed.update;
930
1001
  if (processed.warnings) {
931
1002
  for (const w of processed.warnings) {
932
- const msg = w.kind === 'overlap'
1003
+ const msg = w.kind === "overlap"
933
1004
  ? `same-id overlap at "${w.path}" — terminal-bracket value ${JSON.stringify(w.value)} sets the element base; sub-field overlay applies on top`
934
1005
  : `dropped nested-bracket ${w.op} path "${w.path}" = ${JSON.stringify(w.value)}`;
935
1006
  warnings.push({ _id: String(_id), error: msg });
@@ -939,10 +1010,13 @@ export class Mongo extends Db {
939
1010
  upsert: true,
940
1011
  returnDocument: "after",
941
1012
  includeResultMetadata: true,
942
- ...(processed.arrayFilters ? { arrayFilters: processed.arrayFilters } : {}),
943
- ...this._sessionOpt()
1013
+ ...(processed.arrayFilters
1014
+ ? { arrayFilters: processed.arrayFilters }
1015
+ : {}),
1016
+ ...this._sessionOpt(),
944
1017
  };
945
1018
  (_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);
1019
+ console.error(`[Mongo] updateCollections findOneAndUpdate payload collection=${collection} _id=${String(_id)} clientRev=${clientRev}`, { collection, _id: String(_id), clientRev, filter: { _id: objectId }, update: processed.update });
946
1020
  const res = await conn
947
1021
  .db(dbName)
948
1022
  .collection(collection)
@@ -950,7 +1024,9 @@ export class Mongo extends Db {
950
1024
  if (res === null || res === void 0 ? void 0 : res.value) {
951
1025
  // Determine if this was an insert or update based on lastErrorObject
952
1026
  const wasInsert = !((_b = res.lastErrorObject) === null || _b === void 0 ? void 0 : _b.updatedExisting);
953
- const operation = wasInsert ? 'insert' : 'update';
1027
+ const operation = wasInsert
1028
+ ? "insert"
1029
+ : "update";
954
1030
  // mustRefresh: the client must replace its local copy when cry-db
955
1031
  // resolved a field (SEQ_*/__hashed__) OR a concurrent external write
956
1032
  // advanced the stored `_rev` beyond this write (gap > the +1 this write
@@ -958,10 +1034,10 @@ export class Mongo extends Db {
958
1034
  // old-client fallback. Built from a sanitized clone (hash never leaks).
959
1035
  const writtenRev = res.value._rev;
960
1036
  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)
1037
+ const externallyModified = !wasInsert &&
1038
+ typeof writtenRev === "number" &&
1039
+ writtenRev - inc > (clientRev !== null && clientRev !== void 0 ? clientRev : 0);
1040
+ const mustRefresh = updateResolvedFlags[idx] || externallyModified
965
1041
  ? this._buildMustRefreshRecord(res.value)
966
1042
  : undefined;
967
1043
  // Inserts surface the full doc (query fields must reach the client).
@@ -972,12 +1048,25 @@ export class Mongo extends Db {
972
1048
  ? res.value
973
1049
  : this._buildPublishDelta(res.value, inputUpdate, false);
974
1050
  this._processReturnedObject(retObj);
975
- return { success: true, _id, data: retObj, operation, wasInsert, rawUpdate: wasInsert ? undefined : inputUpdate, mustRefresh };
1051
+ return {
1052
+ success: true,
1053
+ _id,
1054
+ data: retObj,
1055
+ operation,
1056
+ wasInsert,
1057
+ rawUpdate: wasInsert ? undefined : inputUpdate,
1058
+ mustRefresh,
1059
+ };
976
1060
  }
977
- return { success: false, _id, error: 'Operation failed' };
1061
+ return { success: false, _id, error: "Operation failed" };
978
1062
  }
979
1063
  catch (err) {
980
- return { success: false, _id, error: err.message || String(err) };
1064
+ console.error(`[Mongo] updateCollections findOneAndUpdate error collection=${collection} _id=${String(_id)} reason=${err.message || String(err)}`, { collection, _id: String(_id), clientRev, err, update: processedUpdateForDiagnostics });
1065
+ return {
1066
+ success: false,
1067
+ _id,
1068
+ error: err.message || String(err),
1069
+ };
981
1070
  }
982
1071
  });
983
1072
  const updateResults = await Promise.all(updatePromises);
@@ -1021,26 +1110,32 @@ export class Mongo extends Db {
1021
1110
  // Hard delete applies no `_rev` increment: the removed doc's `_rev`
1022
1111
  // exceeding the client's base means an external write landed first.
1023
1112
  // 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);
1113
+ const externallyModified = typeof res._rev === "number" &&
1114
+ res._rev > (clientRev !== null && clientRev !== void 0 ? clientRev : 0);
1026
1115
  const mustRefresh = externallyModified
1027
1116
  ? this._buildMustRefreshRecord(res)
1028
1117
  : undefined;
1029
1118
  this._processReturnedObject(res);
1030
- return { success: true, _id, data: res, operation: 'delete', mustRefresh };
1119
+ return {
1120
+ success: true,
1121
+ _id,
1122
+ data: res,
1123
+ operation: "delete",
1124
+ mustRefresh,
1125
+ };
1031
1126
  }
1032
- return { success: false, _id, error: 'Document not found' };
1127
+ return { success: false, _id, error: "Document not found" };
1033
1128
  }
1034
1129
  else {
1035
1130
  const del = {
1036
1131
  $set: { _deleted: new Date() },
1037
1132
  $inc: { _rev: 1 },
1038
- $currentDate: { _ts: { $type: 'timestamp' } }
1133
+ $currentDate: { _ts: { $type: "timestamp" } },
1039
1134
  };
1040
1135
  const opts = {
1041
1136
  upsert: false,
1042
1137
  returnDocument: "after",
1043
- ...this._sessionOpt()
1138
+ ...this._sessionOpt(),
1044
1139
  };
1045
1140
  const res = await conn
1046
1141
  .db(dbName)
@@ -1050,19 +1145,29 @@ export class Mongo extends Db {
1050
1145
  // Soft delete applied a +1 `_rev` increment: a gap beyond that +1
1051
1146
  // means an external write modified the record before this delete.
1052
1147
  // 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);
1148
+ const externallyModified = typeof res._rev === "number" &&
1149
+ res._rev - 1 > (clientRev !== null && clientRev !== void 0 ? clientRev : 0);
1055
1150
  const mustRefresh = externallyModified
1056
1151
  ? this._buildMustRefreshRecord(res)
1057
1152
  : undefined;
1058
1153
  this._processReturnedObject(res);
1059
- return { success: true, _id, data: res, operation: 'delete', mustRefresh };
1154
+ return {
1155
+ success: true,
1156
+ _id,
1157
+ data: res,
1158
+ operation: "delete",
1159
+ mustRefresh,
1160
+ };
1060
1161
  }
1061
- return { success: false, _id, error: 'Document not found' };
1162
+ return { success: false, _id, error: "Document not found" };
1062
1163
  }
1063
1164
  }
1064
1165
  catch (err) {
1065
- return { success: false, _id, error: err.message || String(err) };
1166
+ return {
1167
+ success: false,
1168
+ _id,
1169
+ error: err.message || String(err),
1170
+ };
1066
1171
  }
1067
1172
  });
1068
1173
  const deleteResults = await Promise.all(deletePromises);
@@ -1099,8 +1204,8 @@ export class Mongo extends Db {
1099
1204
  operation: "batch",
1100
1205
  db: dbName,
1101
1206
  collection,
1102
- data: batchData
1103
- }
1207
+ data: batchData,
1208
+ },
1104
1209
  });
1105
1210
  }
1106
1211
  if (this.emittingPublishRevEvents) {
@@ -1108,11 +1213,11 @@ export class Mongo extends Db {
1108
1213
  operation: "batch",
1109
1214
  db: dbName,
1110
1215
  collection,
1111
- data: batchData.map(item => ({
1216
+ data: batchData.map((item) => ({
1112
1217
  operation: item.operation,
1113
1218
  _id: item.data._id,
1114
1219
  _ts: item.data._ts,
1115
- }))
1220
+ })),
1116
1221
  };
1117
1222
  this.emit("publishRev", {
1118
1223
  channel: `dbrev/${dbName}/${collection}`,
@@ -1128,22 +1233,24 @@ export class Mongo extends Db {
1128
1233
  results.push(result);
1129
1234
  }
1130
1235
  }
1131
- (_c = fjLog === null || fjLog === void 0 ? void 0 : fjLog[debugMethod]) === null || _c === void 0 ? void 0 : _c.call(fjLog, 'updateCollections returns', results);
1236
+ (_c = fjLog === null || fjLog === void 0 ? void 0 : fjLog[debugMethod]) === null || _c === void 0 ? void 0 : _c.call(fjLog, "updateCollections returns", results);
1132
1237
  return results;
1133
1238
  }
1134
1239
  async upsertBatch(collection, batch) {
1135
1240
  assert(collection, "collection is required", "upsertBatch");
1136
1241
  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);
1242
+ assert(batch instanceof Array, "batch must be an Array", "upsertBatch", {
1243
+ collection,
1244
+ });
1245
+ fjLog.debug("upsertBatch called", collection, batch);
1139
1246
  const dbName = this.db; // Capture db at operation start
1140
1247
  batch = this.replaceIds(batch);
1141
- await Promise.all(batch.map(item => this._processHashedKeys(item === null || item === void 0 ? void 0 : item.update)));
1248
+ await Promise.all(batch.map((item) => this._processHashedKeys(item === null || item === void 0 ? void 0 : item.update)));
1142
1249
  let ret = await this.executeTransactionally(collection, async (conn, client) => {
1143
1250
  // Only process sequences if any batch item has SEQ_NEXT or SEQ_LAST
1144
- const updatesWithSeq = batch.filter(b => this._hasSequenceFields(b.update));
1251
+ const updatesWithSeq = batch.filter((b) => this._hasSequenceFields(b.update));
1145
1252
  if (updatesWithSeq.length > 0) {
1146
- await this._processSequenceFieldForMany(client, dbName, collection, updatesWithSeq.map(b => b.update));
1253
+ await this._processSequenceFieldForMany(client, dbName, collection, updatesWithSeq.map((b) => b.update));
1147
1254
  }
1148
1255
  // Process all updates in parallel
1149
1256
  const upsertPromises = batch.map(async (part) => {
@@ -1154,7 +1261,7 @@ export class Mongo extends Db {
1154
1261
  upsert: true,
1155
1262
  returnDocument: "after",
1156
1263
  includeResultMetadata: true,
1157
- ...this._sessionOpt()
1264
+ ...this._sessionOpt(),
1158
1265
  };
1159
1266
  if (this._hasHashedKeys(update))
1160
1267
  await this._processHashedKeys(update);
@@ -1182,7 +1289,11 @@ export class Mongo extends Db {
1182
1289
  ? ret
1183
1290
  : this._buildPublishDelta(ret, inputUpdate, !!(opts === null || opts === void 0 ? void 0 : opts.returnFullObject));
1184
1291
  this._processReturnedObject(retObj);
1185
- return { operation: oper, data: retObj, rawUpdate: oper === 'update' ? inputUpdate : undefined };
1292
+ return {
1293
+ operation: oper,
1294
+ data: retObj,
1295
+ rawUpdate: oper === "update" ? inputUpdate : undefined,
1296
+ };
1186
1297
  });
1187
1298
  const results = await Promise.all(upsertPromises);
1188
1299
  // Filter out nulls and separate batchData and changes
@@ -1205,8 +1316,8 @@ export class Mongo extends Db {
1205
1316
  operation: "batch",
1206
1317
  db: dbName,
1207
1318
  collection,
1208
- data: batchData
1209
- }
1319
+ data: batchData,
1320
+ },
1210
1321
  });
1211
1322
  }
1212
1323
  if (this.emittingPublishRevEvents) {
@@ -1214,11 +1325,11 @@ export class Mongo extends Db {
1214
1325
  operation: "batch",
1215
1326
  db: dbName,
1216
1327
  collection,
1217
- data: batchData.map(item => ({
1328
+ data: batchData.map((item) => ({
1218
1329
  operation: item.operation,
1219
1330
  _id: item.data._id,
1220
1331
  _ts: item.data._ts,
1221
- }))
1332
+ })),
1222
1333
  };
1223
1334
  this.emit("publishRev", {
1224
1335
  channel: `dbrev/${dbName}/${collection}`,
@@ -1227,23 +1338,28 @@ export class Mongo extends Db {
1227
1338
  }
1228
1339
  return changes;
1229
1340
  }, false, { operation: "upsertBatch", collection, batch });
1230
- fjLog.debug('upsertBatch returns', ret);
1341
+ fjLog.debug("upsertBatch returns", ret);
1231
1342
  return ret;
1232
1343
  }
1233
1344
  async insertMany(collection, insert) {
1234
1345
  assert(collection, "collection is required", "insertMany");
1235
1346
  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);
1347
+ assert(insert instanceof Array, "insert must be an Array", "insertMany", {
1348
+ collection,
1349
+ });
1350
+ fjLog.debug("insertMany called", collection, insert);
1238
1351
  const dbName = this.db; // Capture db at operation start
1239
1352
  insert = this.replaceIds(insert);
1240
- insert.forEach(item => this._stripDoubleUnderscoreKeys(item));
1241
- await Promise.all(insert.map(item => this._processHashedKeys(item)));
1353
+ insert.forEach((item) => this._stripDoubleUnderscoreKeys(item));
1354
+ await Promise.all(insert.map((item) => this._processHashedKeys(item)));
1242
1355
  if (this.revisions)
1243
- insert.forEach(ins => { ins._rev = 1; ins._ts = Base.timestamp(); });
1356
+ insert.forEach((ins) => {
1357
+ ins._rev = 1;
1358
+ ins._ts = Base.timestamp();
1359
+ });
1244
1360
  let ret = await this.executeTransactionally(collection, async (conn, client) => {
1245
1361
  // Only process sequences if any insert has SEQ_NEXT or SEQ_LAST
1246
- const insertsWithSeq = insert.filter(item => this._hasSequenceFields(item));
1362
+ const insertsWithSeq = insert.filter((item) => this._hasSequenceFields(item));
1247
1363
  if (insertsWithSeq.length > 0) {
1248
1364
  await this._processSequenceFieldForMany(client, dbName, collection, insert);
1249
1365
  }
@@ -1253,16 +1369,20 @@ export class Mongo extends Db {
1253
1369
  let n = Number(ns);
1254
1370
  let rec = {
1255
1371
  _id: obj.insertedIds[n],
1256
- ...insert[n]
1372
+ ...insert[n],
1257
1373
  };
1258
1374
  ret.push(rec);
1259
1375
  }
1260
- if (this.emittingPublishEvents || this.emittingPublishRevEvents || this.auditing) {
1261
- await Promise.all(ret.filter(rec => rec).map(rec => this._publishAndAudit('insert', dbName, collection, rec)));
1376
+ if (this.emittingPublishEvents ||
1377
+ this.emittingPublishRevEvents ||
1378
+ this.auditing) {
1379
+ await Promise.all(ret
1380
+ .filter((rec) => rec)
1381
+ .map((rec) => this._publishAndAudit("insert", dbName, collection, rec)));
1262
1382
  }
1263
1383
  return ret;
1264
1384
  }, false, { operation: "insertMany", collection, insert });
1265
- fjLog.debug('insertMany returns', ret);
1385
+ fjLog.debug("insertMany returns", ret);
1266
1386
  return ret;
1267
1387
  }
1268
1388
  async deleteOne(collection, query) {
@@ -1272,36 +1392,46 @@ export class Mongo extends Db {
1272
1392
  query = this.replaceIds(query);
1273
1393
  if (!this.softdelete) {
1274
1394
  const opts = this._sessionOpt();
1275
- fjLog.debug('deleteOne called', this.softdelete, collection, query);
1395
+ fjLog.debug("deleteOne called", this.softdelete, collection, query);
1276
1396
  let ret = await this.executeTransactionally(collection, async (conn) => {
1277
1397
  let obj = await conn.findOneAndDelete(query, opts);
1278
1398
  if (obj)
1279
- await this._publishAndAudit('delete', dbName, collection, obj);
1399
+ await this._publishAndAudit("delete", dbName, collection, obj);
1280
1400
  return obj;
1281
- }, false, { operation: "deleteOne", collection, query, softdelete: this.softdelete });
1282
- fjLog.debug('deleteOne returns', ret);
1401
+ }, false, {
1402
+ operation: "deleteOne",
1403
+ collection,
1404
+ query,
1405
+ softdelete: this.softdelete,
1406
+ });
1407
+ fjLog.debug("deleteOne returns", ret);
1283
1408
  return ret;
1284
1409
  }
1285
1410
  else {
1286
1411
  let opts = {
1287
1412
  upsert: false,
1288
1413
  returnDocument: "after",
1289
- ...this._sessionOpt()
1414
+ ...this._sessionOpt(),
1290
1415
  };
1291
- fjLog.debug('deleteOne called', collection, query);
1416
+ fjLog.debug("deleteOne called", collection, query);
1292
1417
  let ret = await this.executeTransactionally(collection, async (conn /*, client*/) => {
1293
1418
  let del = {
1294
1419
  $set: { _deleted: new Date() },
1295
- $inc: { _rev: 1, },
1296
- $currentDate: { _ts: { $type: 'timestamp' } }
1420
+ $inc: { _rev: 1 },
1421
+ $currentDate: { _ts: { $type: "timestamp" } },
1297
1422
  };
1298
1423
  // if (this.syncSupport) del.$set._csq = await this._getNextCollectionUpdateSeqNo(collection, client)
1299
1424
  let obj = await conn.findOneAndUpdate(query, del, opts);
1300
1425
  if (obj)
1301
- await this._publishAndAudit('delete', dbName, collection, obj);
1426
+ await this._publishAndAudit("delete", dbName, collection, obj);
1302
1427
  return obj;
1303
- }, false, { operation: "deleteOne", collection, query, softdelete: this.softdelete });
1304
- fjLog.debug('deleteOne returns', ret);
1428
+ }, false, {
1429
+ operation: "deleteOne",
1430
+ collection,
1431
+ query,
1432
+ softdelete: this.softdelete,
1433
+ });
1434
+ fjLog.debug("deleteOne returns", ret);
1305
1435
  return ret;
1306
1436
  }
1307
1437
  }
@@ -1309,56 +1439,56 @@ export class Mongo extends Db {
1309
1439
  let opts = {
1310
1440
  upsert: false,
1311
1441
  returnDocument: "after",
1312
- ...this._sessionOpt()
1442
+ ...this._sessionOpt(),
1313
1443
  };
1314
1444
  const dbName = this.db; // Capture db at operation start
1315
1445
  query = this.replaceIds(query);
1316
- fjLog.debug('blockOne called', collection, query);
1446
+ fjLog.debug("blockOne called", collection, query);
1317
1447
  let ret = await this.executeTransactionally(collection, async (conn) => {
1318
1448
  query._blocked = { $exists: 0 };
1319
1449
  let update = {
1320
- $set: { _blocked: new Date(), },
1321
- $inc: { _rev: 1, },
1322
- $currentDate: { _ts: { $type: 'timestamp' } }
1450
+ $set: { _blocked: new Date() },
1451
+ $inc: { _rev: 1 },
1452
+ $currentDate: { _ts: { $type: "timestamp" } },
1323
1453
  };
1324
1454
  // if (this.syncSupport) update.$set._csq = await this._getNextCollectionUpdateSeqNo(collection, client)
1325
1455
  let obj = await conn.findOneAndUpdate(query, update, opts);
1326
1456
  if (!obj || !(obj === null || obj === void 0 ? void 0 : obj._id))
1327
1457
  return {
1328
- ok: false
1458
+ ok: false,
1329
1459
  };
1330
- await this._publishAndAudit('update', dbName, collection, obj);
1460
+ await this._publishAndAudit("update", dbName, collection, obj);
1331
1461
  return obj;
1332
1462
  }, false, { operation: "blockOne", collection, query });
1333
- fjLog.debug('blockOne returns', ret);
1463
+ fjLog.debug("blockOne returns", ret);
1334
1464
  return ret;
1335
1465
  }
1336
1466
  async unblockOne(collection, query) {
1337
1467
  let opts = {
1338
1468
  upsert: false,
1339
1469
  returnDocument: "after",
1340
- ...this._sessionOpt()
1470
+ ...this._sessionOpt(),
1341
1471
  };
1342
1472
  const dbName = this.db; // Capture db at operation start
1343
1473
  query = this.replaceIds(query);
1344
- fjLog.debug('unblockOne called', collection, query);
1474
+ fjLog.debug("unblockOne called", collection, query);
1345
1475
  let ret = await this.executeTransactionally(collection, async (conn) => {
1346
1476
  query._blocked = { $exists: 1 };
1347
1477
  let update = {
1348
1478
  $unset: { _blocked: 1 },
1349
- $inc: { _rev: 1, },
1350
- $currentDate: { _ts: { $type: 'timestamp' } }
1479
+ $inc: { _rev: 1 },
1480
+ $currentDate: { _ts: { $type: "timestamp" } },
1351
1481
  };
1352
1482
  // if (this.syncSupport) update.$set = { _csq: await this._getNextCollectionUpdateSeqNo(collection, client) };
1353
1483
  let obj = await conn.findOneAndUpdate(query, update, opts);
1354
1484
  if (!obj || !(obj === null || obj === void 0 ? void 0 : obj._id))
1355
1485
  return {
1356
- ok: false
1486
+ ok: false,
1357
1487
  };
1358
- await this._publishAndAudit('update', dbName, collection, obj);
1488
+ await this._publishAndAudit("update", dbName, collection, obj);
1359
1489
  return obj;
1360
1490
  }, false, { operation: "unblockOne", collection, query });
1361
- fjLog.debug('unblockOne returns', ret);
1491
+ fjLog.debug("unblockOne returns", ret);
1362
1492
  return ret;
1363
1493
  }
1364
1494
  /**
@@ -1369,27 +1499,27 @@ export class Mongo extends Db {
1369
1499
  let opts = {
1370
1500
  upsert: false,
1371
1501
  returnDocument: "after",
1372
- ...this._sessionOpt()
1502
+ ...this._sessionOpt(),
1373
1503
  };
1374
1504
  const dbName = this.db;
1375
1505
  query = this.replaceIds(query);
1376
- fjLog.debug('archiveOne called', collection, query);
1506
+ fjLog.debug("archiveOne called", collection, query);
1377
1507
  let ret = await this.executeTransactionally(collection, async (conn) => {
1378
1508
  query._archived = { $exists: false };
1379
1509
  let update = {
1380
- $set: { _archived: new Date(), },
1381
- $inc: { _rev: 1, },
1382
- $currentDate: { _ts: { $type: 'timestamp' } }
1510
+ $set: { _archived: new Date() },
1511
+ $inc: { _rev: 1 },
1512
+ $currentDate: { _ts: { $type: "timestamp" } },
1383
1513
  };
1384
1514
  let obj = await conn.findOneAndUpdate(query, update, opts);
1385
1515
  if (!obj || !(obj === null || obj === void 0 ? void 0 : obj._id))
1386
1516
  return {
1387
- ok: false
1517
+ ok: false,
1388
1518
  };
1389
- await this._publishAndAudit('update', dbName, collection, obj);
1519
+ await this._publishAndAudit("update", dbName, collection, obj);
1390
1520
  return obj;
1391
1521
  }, false, { operation: "archiveOne", collection, query });
1392
- fjLog.debug('archiveOne returns', ret);
1522
+ fjLog.debug("archiveOne returns", ret);
1393
1523
  return ret;
1394
1524
  }
1395
1525
  /**
@@ -1400,27 +1530,27 @@ export class Mongo extends Db {
1400
1530
  let opts = {
1401
1531
  upsert: false,
1402
1532
  returnDocument: "after",
1403
- ...this._sessionOpt()
1533
+ ...this._sessionOpt(),
1404
1534
  };
1405
1535
  const dbName = this.db;
1406
1536
  query = this.replaceIds(query);
1407
- fjLog.debug('unarchiveOne called', collection, query);
1537
+ fjLog.debug("unarchiveOne called", collection, query);
1408
1538
  let ret = await this.executeTransactionally(collection, async (conn) => {
1409
1539
  query._archived = { $exists: true };
1410
1540
  let update = {
1411
1541
  $unset: { _archived: 1 },
1412
- $inc: { _rev: 1, },
1413
- $currentDate: { _ts: { $type: 'timestamp' } }
1542
+ $inc: { _rev: 1 },
1543
+ $currentDate: { _ts: { $type: "timestamp" } },
1414
1544
  };
1415
1545
  let obj = await conn.findOneAndUpdate(query, update, opts);
1416
1546
  if (!obj || !(obj === null || obj === void 0 ? void 0 : obj._id))
1417
1547
  return {
1418
- ok: false
1548
+ ok: false,
1419
1549
  };
1420
- await this._publishAndAudit('update', dbName, collection, obj);
1550
+ await this._publishAndAudit("update", dbName, collection, obj);
1421
1551
  return obj;
1422
1552
  }, false, { operation: "unarchiveOne", collection, query });
1423
- fjLog.debug('unarchiveOne returns', ret);
1553
+ fjLog.debug("unarchiveOne returns", ret);
1424
1554
  return ret;
1425
1555
  }
1426
1556
  /**
@@ -1429,7 +1559,9 @@ export class Mongo extends Db {
1429
1559
  async archiveOneById(collection, id) {
1430
1560
  assert(collection, "collection is required", "archiveOneById");
1431
1561
  assert(id, "id is required", "archiveOneById", { collection });
1432
- return await this.archiveOne(collection, { _id: Mongo._toId(id) });
1562
+ return await this.archiveOne(collection, {
1563
+ _id: Mongo._toId(id),
1564
+ });
1433
1565
  }
1434
1566
  /**
1435
1567
  * Archives multiple documents found by their `_id`s.
@@ -1443,29 +1575,32 @@ export class Mongo extends Db {
1443
1575
  const opts = {
1444
1576
  upsert: false,
1445
1577
  returnDocument: "after",
1446
- ...this._sessionOpt()
1578
+ ...this._sessionOpt(),
1447
1579
  };
1448
1580
  const dbName = this.db;
1449
- fjLog.debug('archiveManyByIds called', collection, ids);
1581
+ fjLog.debug("archiveManyByIds called", collection, ids);
1450
1582
  let ret = [];
1451
1583
  for (const id of ids) {
1452
1584
  let r = await this.executeTransactionally(collection, async (conn) => {
1453
- let query = { _id: Mongo._toId(id), _archived: { $exists: false } };
1585
+ let query = {
1586
+ _id: Mongo._toId(id),
1587
+ _archived: { $exists: false },
1588
+ };
1454
1589
  let update = {
1455
1590
  $set: { _archived: new Date() },
1456
1591
  $inc: { _rev: 1 },
1457
- $currentDate: { _ts: { $type: 'timestamp' } }
1592
+ $currentDate: { _ts: { $type: "timestamp" } },
1458
1593
  };
1459
1594
  let obj = await conn.findOneAndUpdate(query, update, opts);
1460
1595
  if (obj === null || obj === void 0 ? void 0 : obj._id) {
1461
- await this._publishAndAudit('update', dbName, collection, obj);
1596
+ await this._publishAndAudit("update", dbName, collection, obj);
1462
1597
  }
1463
1598
  return obj;
1464
1599
  }, false, { operation: "archiveManyByIds", collection, id });
1465
1600
  if (r === null || r === void 0 ? void 0 : r._id)
1466
1601
  ret.push(r);
1467
1602
  }
1468
- fjLog.debug('archiveManyByIds returns', ret);
1603
+ fjLog.debug("archiveManyByIds returns", ret);
1469
1604
  return ret;
1470
1605
  }
1471
1606
  /**
@@ -1474,7 +1609,9 @@ export class Mongo extends Db {
1474
1609
  async unarchiveOneById(collection, id) {
1475
1610
  assert(collection, "collection is required", "unarchiveOneById");
1476
1611
  assert(id, "id is required", "unarchiveOneById", { collection });
1477
- return await this.unarchiveOne(collection, { _id: Mongo._toId(id) });
1612
+ return await this.unarchiveOne(collection, {
1613
+ _id: Mongo._toId(id),
1614
+ });
1478
1615
  }
1479
1616
  /**
1480
1617
  * Unarchives multiple documents found by their `_id`s.
@@ -1488,52 +1625,57 @@ export class Mongo extends Db {
1488
1625
  const opts = {
1489
1626
  upsert: false,
1490
1627
  returnDocument: "after",
1491
- ...this._sessionOpt()
1628
+ ...this._sessionOpt(),
1492
1629
  };
1493
1630
  const dbName = this.db;
1494
- fjLog.debug('unarchiveManyByIds called', collection, ids);
1631
+ fjLog.debug("unarchiveManyByIds called", collection, ids);
1495
1632
  let ret = [];
1496
1633
  for (const id of ids) {
1497
1634
  let r = await this.executeTransactionally(collection, async (conn) => {
1498
- let query = { _id: Mongo._toId(id), _archived: { $exists: true } };
1635
+ let query = {
1636
+ _id: Mongo._toId(id),
1637
+ _archived: { $exists: true },
1638
+ };
1499
1639
  let update = {
1500
1640
  $unset: { _archived: 1 },
1501
1641
  $inc: { _rev: 1 },
1502
- $currentDate: { _ts: { $type: 'timestamp' } }
1642
+ $currentDate: { _ts: { $type: "timestamp" } },
1503
1643
  };
1504
1644
  let obj = await conn.findOneAndUpdate(query, update, opts);
1505
1645
  if (obj === null || obj === void 0 ? void 0 : obj._id) {
1506
- await this._publishAndAudit('update', dbName, collection, obj);
1646
+ await this._publishAndAudit("update", dbName, collection, obj);
1507
1647
  }
1508
1648
  return obj;
1509
1649
  }, false, { operation: "unarchiveManyByIds", collection, id });
1510
1650
  if (r === null || r === void 0 ? void 0 : r._id)
1511
1651
  ret.push(r);
1512
1652
  }
1513
- fjLog.debug('unarchiveManyByIds returns', ret);
1653
+ fjLog.debug("unarchiveManyByIds returns", ret);
1514
1654
  return ret;
1515
1655
  }
1516
1656
  async hardDeleteOne(collection, query) {
1517
1657
  assert(collection, "collection is required", "hardDeleteOne");
1518
1658
  assert(query, "query is required", "hardDeleteOne", { collection });
1519
1659
  const dbName = this.db; // Capture db at operation start
1520
- if (typeof query === "string" || typeof query === "number" || query instanceof ObjectId) {
1660
+ if (typeof query === "string" ||
1661
+ typeof query === "number" ||
1662
+ query instanceof ObjectId) {
1521
1663
  query = { _id: query };
1522
1664
  }
1523
1665
  query = this.replaceIds(query);
1524
1666
  let opts = {
1525
1667
  returnDocument: "after",
1526
- ...this._sessionOpt()
1668
+ ...this._sessionOpt(),
1527
1669
  };
1528
- fjLog.debug('hardDeleteOne called', collection, query);
1670
+ fjLog.debug("hardDeleteOne called", collection, query);
1529
1671
  let ret = await this.executeTransactionally(collection, async (conn) => {
1530
1672
  let obj = await conn.findOneAndDelete(query, opts);
1531
1673
  if (obj) {
1532
- await this._publishAndAudit('delete', dbName, collection, obj);
1674
+ await this._publishAndAudit("delete", dbName, collection, obj);
1533
1675
  }
1534
1676
  return obj;
1535
1677
  }, false, { operation: "hardDeleteOne", collection, query });
1536
- fjLog.debug('hardDeleteOne returns', ret);
1678
+ fjLog.debug("hardDeleteOne returns", ret);
1537
1679
  return ret;
1538
1680
  }
1539
1681
  async delete(collection, query) {
@@ -1544,42 +1686,42 @@ export class Mongo extends Db {
1544
1686
  query = this.replaceIds(query);
1545
1687
  if (!this.softdelete) {
1546
1688
  const opts = this._sessionOpt();
1547
- fjLog.debug('delete called', collection, query);
1689
+ fjLog.debug("delete called", collection, query);
1548
1690
  let ret = await this.executeTransactionally(collection, async (conn) => {
1549
1691
  let obj = await conn.deleteMany(query, opts);
1550
1692
  let resObj = {
1551
1693
  n: obj.deletedCount,
1552
- ok: !!obj.acknowledged
1694
+ ok: !!obj.acknowledged,
1553
1695
  };
1554
- await this._publishAndAudit('deleteMany', dbName, collection, resObj);
1696
+ await this._publishAndAudit("deleteMany", dbName, collection, resObj);
1555
1697
  return resObj;
1556
1698
  }, false, { operation: "delete", collection, query, softdelete: this.softdelete });
1557
- fjLog.debug('delete returns', ret);
1699
+ fjLog.debug("delete returns", ret);
1558
1700
  return ret;
1559
1701
  }
1560
1702
  else {
1561
1703
  let opts = {
1562
1704
  upsert: false,
1563
1705
  returnDocument: "after",
1564
- ...this._sessionOpt()
1706
+ ...this._sessionOpt(),
1565
1707
  };
1566
1708
  let date = new Date();
1567
- fjLog.debug('delete called', collection, query);
1709
+ fjLog.debug("delete called", collection, query);
1568
1710
  let ret = await this.executeTransactionally(collection, async (conn) => {
1569
1711
  let upd = {
1570
1712
  $set: { _deleted: date },
1571
1713
  $inc: { _rev: 1 },
1572
- $currentDate: { _ts: { $type: 'timestamp' } }
1714
+ $currentDate: { _ts: { $type: "timestamp" } },
1573
1715
  };
1574
1716
  let obj = await conn.updateMany(query, upd, opts);
1575
1717
  let resObj = {
1576
1718
  n: obj.modifiedCount,
1577
- ok: !!obj.acknowledged
1719
+ ok: !!obj.acknowledged,
1578
1720
  };
1579
- await this._publishAndAudit('deleteMany', dbName, collection, resObj);
1721
+ await this._publishAndAudit("deleteMany", dbName, collection, resObj);
1580
1722
  return resObj;
1581
1723
  }, false, { operation: "delete", collection, query, softdelete: this.softdelete });
1582
- fjLog.debug('delete returns', ret);
1724
+ fjLog.debug("delete returns", ret);
1583
1725
  return ret;
1584
1726
  }
1585
1727
  }
@@ -1590,22 +1732,27 @@ export class Mongo extends Db {
1590
1732
  const dbName = this.db; // Capture db at operation start
1591
1733
  query = this.replaceIds(query);
1592
1734
  const opts = this._sessionOpt();
1593
- fjLog.debug('hardDelete called', collection, query);
1735
+ fjLog.debug("hardDelete called", collection, query);
1594
1736
  let ret = await this.executeTransactionally(collection, async (conn) => {
1595
1737
  let obj = await conn.deleteMany(query, opts);
1596
1738
  let resObj = {
1597
1739
  n: obj.deletedCount,
1598
- ok: !!obj.acknowledged
1740
+ ok: !!obj.acknowledged,
1599
1741
  };
1600
- await this._publishAndAudit('deleteMany', dbName, collection, resObj);
1742
+ await this._publishAndAudit("deleteMany", dbName, collection, resObj);
1601
1743
  return resObj;
1602
- }, false, { operation: "hardDelete", collection, query, softdelete: this.softdelete });
1603
- fjLog.debug('hardDelete returns', ret);
1744
+ }, false, {
1745
+ operation: "hardDelete",
1746
+ collection,
1747
+ query,
1748
+ softdelete: this.softdelete,
1749
+ });
1750
+ fjLog.debug("hardDelete returns", ret);
1604
1751
  return ret;
1605
1752
  }
1606
1753
  async testHash(collection, query, field, unhashedValue) {
1607
1754
  let _field;
1608
- fjLog.debug('testHash called', collection, query, field, unhashedValue);
1755
+ fjLog.debug("testHash called", collection, query, field, unhashedValue);
1609
1756
  if (typeof field === "object") {
1610
1757
  if (Object.keys(field).length === 1)
1611
1758
  [_field, unhashedValue] = Object.entries(field)[0];
@@ -1618,13 +1765,16 @@ export class Mongo extends Db {
1618
1765
  _field = HASHED_PREFIX + _field;
1619
1766
  const dbName = this.db; // Capture db at operation start
1620
1767
  let conn = await this.connect();
1621
- let obj = await conn.db(dbName).collection(collection).findOne(query, { projection: { [_field]: 1 }, ...this._sessionOpt() });
1768
+ let obj = await conn
1769
+ .db(dbName)
1770
+ .collection(collection)
1771
+ .findOne(query, { projection: { [_field]: 1 }, ...this._sessionOpt() });
1622
1772
  if (!obj || !obj[_field]) {
1623
- fjLog.debug('testHash returns false', obj);
1773
+ fjLog.debug("testHash returns false", obj);
1624
1774
  return false;
1625
1775
  }
1626
1776
  let res = await bcrypt.compare(unhashedValue, obj[_field].hash);
1627
- fjLog.debug('testHash returns', res);
1777
+ fjLog.debug("testHash returns", res);
1628
1778
  return res;
1629
1779
  }
1630
1780
  async aggregate(collection, pipeline, opts = {
@@ -1632,7 +1782,7 @@ export class Mongo extends Db {
1632
1782
  }) {
1633
1783
  assert(collection, "collection is required", "aggregate");
1634
1784
  assert(pipeline instanceof Array, "pipeline must be an Array", "aggregate", { collection });
1635
- fjLog.debug('aggregate called', collection, pipeline);
1785
+ fjLog.debug("aggregate called", collection, pipeline);
1636
1786
  pipeline = this.replaceIds(pipeline);
1637
1787
  if (this.session)
1638
1788
  opts.session = this.session;
@@ -1640,7 +1790,7 @@ export class Mongo extends Db {
1640
1790
  let res = await conn.aggregate(pipeline, opts).toArray();
1641
1791
  return res;
1642
1792
  }, false, { operation: "aggregate", collection, pipeline, opts });
1643
- fjLog.debug('aggregare returns', ret);
1793
+ fjLog.debug("aggregare returns", ret);
1644
1794
  return ret;
1645
1795
  }
1646
1796
  async isUnique(collection, field, value, id) {
@@ -1648,7 +1798,7 @@ export class Mongo extends Db {
1648
1798
  assert(field, "field is required", "isUnique", { collection });
1649
1799
  if (!value)
1650
1800
  return false;
1651
- fjLog.debug('isUnique called', collection, field, value, id);
1801
+ fjLog.debug("isUnique called", collection, field, value, id);
1652
1802
  let _id = id === null || id === void 0 ? void 0 : id.toString();
1653
1803
  let query = typeof value === "object" ? value : { [field]: value };
1654
1804
  query = this.replaceIds(query);
@@ -1666,12 +1816,12 @@ export class Mongo extends Db {
1666
1816
  return false;
1667
1817
  }
1668
1818
  }
1669
- fjLog.debug('isUnique returns', ret);
1819
+ fjLog.debug("isUnique returns", ret);
1670
1820
  return ret;
1671
1821
  }
1672
1822
  async dropCollection(collection) {
1673
1823
  assert(collection, "collection is required", "dropCollection");
1674
- fjLog.debug('dropCollection called', this.auditCollections);
1824
+ fjLog.debug("dropCollection called", this.auditCollections);
1675
1825
  const dbName = this.db; // Capture db at operation start
1676
1826
  let client = await this.connect();
1677
1827
  let existing = await client.db(dbName).collections();
@@ -1679,14 +1829,15 @@ export class Mongo extends Db {
1679
1829
  if (existingNames.has(collection)) {
1680
1830
  await client.db(dbName).dropCollection(collection);
1681
1831
  }
1682
- fjLog.debug('dropCollection returns');
1832
+ fjLog.debug("dropCollection returns");
1683
1833
  }
1684
1834
  async resetCollectionSync(collection) {
1685
1835
  assert(collection, "collection is required", "resetCollectionSync");
1686
- fjLog.debug('resetCollectionSync called for', collection);
1836
+ fjLog.debug("resetCollectionSync called for", collection);
1687
1837
  const dbName = this.db; // Capture db at operation start
1688
1838
  let client = await this.connect();
1689
- await client.db(dbName)
1839
+ await client
1840
+ .db(dbName)
1690
1841
  .collection(SEQUENCES_COLLECTION)
1691
1842
  .findOneAndDelete({ collection });
1692
1843
  fjLog.debug(`resetCollectionSync for ${collection} returns`);
@@ -1694,7 +1845,7 @@ export class Mongo extends Db {
1694
1845
  async dropCollections(collections) {
1695
1846
  assert(collections, "collections is required", "dropCollections");
1696
1847
  assert(collections instanceof Array, "collections must be an Array", "dropCollections");
1697
- fjLog.debug('dropCollections called', this.auditCollections);
1848
+ fjLog.debug("dropCollections called", this.auditCollections);
1698
1849
  const dbName = this.db; // Capture db at operation start
1699
1850
  let client = await this.connect();
1700
1851
  let existing = await client.db(dbName).collections();
@@ -1704,12 +1855,12 @@ export class Mongo extends Db {
1704
1855
  await client.db(dbName).dropCollection(collection);
1705
1856
  }
1706
1857
  }
1707
- fjLog.debug('dropCollections returns');
1858
+ fjLog.debug("dropCollections returns");
1708
1859
  }
1709
1860
  async createCollections(collections) {
1710
1861
  assert(collections, "collections is required", "createCollections");
1711
1862
  assert(collections instanceof Array, "collections must be an Array", "createCollections");
1712
- fjLog.debug('createCollections called', this.auditCollections);
1863
+ fjLog.debug("createCollections called", this.auditCollections);
1713
1864
  const dbName = this.db; // Capture db at operation start
1714
1865
  let client = await this.connect();
1715
1866
  let existing = await this.getCollections();
@@ -1719,25 +1870,25 @@ export class Mongo extends Db {
1719
1870
  await client.db(dbName).createCollection(collection);
1720
1871
  }
1721
1872
  }
1722
- fjLog.debug('createCollections returns');
1873
+ fjLog.debug("createCollections returns");
1723
1874
  }
1724
1875
  async createCollection(collection) {
1725
1876
  assert(collection, "collection is required", "createCollection");
1726
- fjLog.debug('createCollection called', collection);
1877
+ fjLog.debug("createCollection called", collection);
1727
1878
  const dbName = this.db; // Capture db at operation start
1728
1879
  let client = await this.connect();
1729
1880
  let existing = await this.getCollections();
1730
1881
  if (!existing.includes(collection)) {
1731
1882
  await client.db(dbName).createCollection(collection);
1732
1883
  }
1733
- fjLog.debug('createCollection returns');
1884
+ fjLog.debug("createCollection returns");
1734
1885
  }
1735
1886
  async dbLogPurge(collection, _id) {
1736
1887
  assert(collection, "collection is required", "dbLogPurge");
1737
- fjLog.debug('dblogPurge called', collection, _id);
1888
+ fjLog.debug("dblogPurge called", collection, _id);
1738
1889
  const dbName = this.db; // Capture db at operation start
1739
1890
  let ret = await this.executeTransactionally(collection, async () => {
1740
- let cond = { db: dbName, collection, };
1891
+ let cond = { db: dbName, collection };
1741
1892
  if (_id !== undefined)
1742
1893
  cond._id = Mongo._toId(_id);
1743
1894
  let client = await this.connect();
@@ -1747,15 +1898,15 @@ export class Mongo extends Db {
1747
1898
  .deleteMany(cond, this._sessionOpt());
1748
1899
  return {
1749
1900
  ok: !!ret.acknowledged,
1750
- n: ret.deletedCount
1901
+ n: ret.deletedCount,
1751
1902
  };
1752
1903
  }, false, { operation: "dbLogPurge", collection, _id });
1753
- fjLog.debug('dblogPurge returns', ret);
1904
+ fjLog.debug("dblogPurge returns", ret);
1754
1905
  return ret;
1755
1906
  }
1756
1907
  async dbLogGet(collection, _id) {
1757
1908
  assert(collection, "collection is required", "dbLogGet");
1758
- fjLog.debug('dblogGet called', collection, _id);
1909
+ fjLog.debug("dblogGet called", collection, _id);
1759
1910
  const dbName = this.db; // Capture db at operation start
1760
1911
  let ret = await this.executeTransactionally(collection, async () => {
1761
1912
  let cond = { db: dbName, collection };
@@ -1770,7 +1921,7 @@ export class Mongo extends Db {
1770
1921
  .toArray();
1771
1922
  return ret;
1772
1923
  }, false, { operation: "dbLogGet", collection, _id });
1773
- fjLog.debug('dblogGet returns', ret);
1924
+ fjLog.debug("dblogGet returns", ret);
1774
1925
  return ret;
1775
1926
  }
1776
1927
  // HELPER FUNCTIONS
@@ -1805,13 +1956,13 @@ export class Mongo extends Db {
1805
1956
  if (typeof data === "string")
1806
1957
  return data;
1807
1958
  if (data instanceof Array) {
1808
- return data.map(d => this.replaceIds(d));
1959
+ return data.map((d) => this.replaceIds(d));
1809
1960
  }
1810
- if (typeof data == 'object' && (data === null || data === void 0 ? void 0 : data.t) && (data === null || data === void 0 ? void 0 : data.i) !== undefined)
1961
+ if (typeof data == "object" && (data === null || data === void 0 ? void 0 : data.t) && (data === null || data === void 0 ? void 0 : data.i) !== undefined)
1811
1962
  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)
1963
+ if (typeof data == "object" && (data === null || data === void 0 ? void 0 : data.high) && (data === null || data === void 0 ? void 0 : data.low) !== undefined)
1813
1964
  return Base.timestamp(data);
1814
- if (typeof data == 'object') {
1965
+ if (typeof data == "object") {
1815
1966
  for (let key in data) {
1816
1967
  data[key] = this.replaceIds(data[key]);
1817
1968
  }
@@ -1820,7 +1971,7 @@ export class Mongo extends Db {
1820
1971
  throw new Error(`ObjectId test failed for ${data}`);
1821
1972
  }
1822
1973
  catch (err) {
1823
- console.error('error in replaceIds', err, data);
1974
+ console.error("error in replaceIds", err, data);
1824
1975
  throw err;
1825
1976
  }
1826
1977
  }
@@ -1868,14 +2019,14 @@ export class Mongo extends Db {
1868
2019
  this._sequencesIndexEnsured = false;
1869
2020
  }
1870
2021
  async inTransaction() {
1871
- if (!await this.isOnReplicaSet())
2022
+ if (!(await this.isOnReplicaSet()))
1872
2023
  return false;
1873
2024
  if (!this.session)
1874
2025
  return false;
1875
2026
  return this.session.inTransaction();
1876
2027
  }
1877
2028
  async withTransaction(funct) {
1878
- if (!await this.isOnReplicaSet())
2029
+ if (!(await this.isOnReplicaSet()))
1879
2030
  return await funct(await this.connect(), null);
1880
2031
  const hadSession = !!this.session;
1881
2032
  try {
@@ -1899,14 +2050,16 @@ export class Mongo extends Db {
1899
2050
  await this.session.endSession();
1900
2051
  fjLog.info("session ended after error");
1901
2052
  }
1902
- catch { /* ignore cleanup errors */ }
2053
+ catch {
2054
+ /* ignore cleanup errors */
2055
+ }
1903
2056
  this.session = undefined;
1904
2057
  }
1905
2058
  throw err;
1906
2059
  }
1907
2060
  }
1908
2061
  async startTransaction() {
1909
- if (!await this.isOnReplicaSet())
2062
+ if (!(await this.isOnReplicaSet()))
1910
2063
  return;
1911
2064
  let client = await this.connect();
1912
2065
  try {
@@ -1914,13 +2067,13 @@ export class Mongo extends Db {
1914
2067
  this.session = client.startSession(TRANSACTION_OPTIONS);
1915
2068
  fjLog.info("session started");
1916
2069
  }
1917
- if (!await this.inTransaction()) {
2070
+ if (!(await this.inTransaction())) {
1918
2071
  await this.session.startTransaction();
1919
2072
  fjLog.info("transaction started");
1920
2073
  }
1921
2074
  }
1922
2075
  catch (err) {
1923
- fjLog.error('startTransaction error', err);
2076
+ fjLog.error("startTransaction error", err);
1924
2077
  try {
1925
2078
  if (this.session) {
1926
2079
  await this.session.endSession();
@@ -1935,10 +2088,10 @@ export class Mongo extends Db {
1935
2088
  }
1936
2089
  }
1937
2090
  async commitTransaction() {
1938
- if (!await this.isOnReplicaSet())
2091
+ if (!(await this.isOnReplicaSet()))
1939
2092
  return;
1940
2093
  try {
1941
- if (!await this.inTransaction())
2094
+ if (!(await this.inTransaction()))
1942
2095
  return;
1943
2096
  let session = this.session;
1944
2097
  await session.commitTransaction();
@@ -1952,10 +2105,10 @@ export class Mongo extends Db {
1952
2105
  }
1953
2106
  }
1954
2107
  async abortTransaction() {
1955
- if (!await this.isOnReplicaSet())
2108
+ if (!(await this.isOnReplicaSet()))
1956
2109
  return;
1957
2110
  try {
1958
- if (!await this.inTransaction())
2111
+ if (!(await this.inTransaction()))
1959
2112
  return;
1960
2113
  let session = this.session;
1961
2114
  await session.abortTransaction();
@@ -2009,22 +2162,24 @@ export class Mongo extends Db {
2009
2162
  // E11000 duplicate key — log concise one-liner (avoid dumping full batch)
2010
2163
  if (x.match(/E11000/i)) {
2011
2164
  const dupMatch = x.match(/dup key:\s*(\{[^}]+\})/);
2012
- const count = Array.isArray(debugObject.insert) ? debugObject.insert.length : 1;
2165
+ const count = Array.isArray(debugObject.insert)
2166
+ ? debugObject.insert.length
2167
+ : 1;
2013
2168
  const rollback = this.session ? "ROLLBACK - " : "";
2014
2169
  fjLog.error(`${rollback}Mongo ${debugObject.operation} E11000 on ${dbName}.${collection} (batch=${count}${dupMatch ? `, ${dupMatch[1].trim()}` : ""}) — ignoring`);
2015
2170
  if (debugObject.operation === "insert")
2016
2171
  return debugObject.insert;
2017
2172
  throw err;
2018
2173
  }
2019
- fjLog.error(`Mongo command has failed for ${dbName}.${collection} - ${(this.session ? "ROLLBACK - " : "")} ${err.message || err}`);
2174
+ fjLog.error(`Mongo command has failed for ${dbName}.${collection} - ${this.session ? "ROLLBACK - " : ""} ${err.message || err}`);
2020
2175
  fjLog.error(debugObject);
2021
2176
  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);
2177
+ let isRepeatable = x.match(/Topology is closed, please connect/i) ||
2178
+ x.match(/connection timed out/i) ||
2179
+ x.match(/not master/i) ||
2180
+ x.match(/Topology closed/i) ||
2181
+ x.match(/Topology is closed/i) ||
2182
+ x.match(/Connection pool closed/i);
2028
2183
  if (isRepeatable) {
2029
2184
  try {
2030
2185
  fjLog.error("Trying to reopen connection and repeat as");
@@ -2049,11 +2204,11 @@ export class Mongo extends Db {
2049
2204
  }
2050
2205
  async _findLastSequenceForKey(connection, key) {
2051
2206
  var _a;
2052
- let maxfld = await (connection
2207
+ let maxfld = await connection
2053
2208
  .find({}, this._sessionOpt())
2054
2209
  .sort({ [key]: -1 })
2055
2210
  .limit(1)
2056
- .toArray());
2211
+ .toArray();
2057
2212
  if (maxfld.length === 0)
2058
2213
  return undefined;
2059
2214
  return parseInt((_a = maxfld === null || maxfld === void 0 ? void 0 : maxfld[0]) === null || _a === void 0 ? void 0 : _a[key]) || 0;
@@ -2095,19 +2250,19 @@ export class Mongo extends Db {
2095
2250
  if (!existingSeq) {
2096
2251
  // First time for this collection/field - ensure index exists
2097
2252
  await this._ensureSequencesIndex(dbConnection);
2098
- const seedValue = (existingMax !== undefined && existingMax >= 1) ? existingMax : 0;
2253
+ const seedValue = existingMax !== undefined && existingMax >= 1 ? existingMax : 0;
2099
2254
  // Use $max to handle concurrent seeding - only sets if greater than current value
2100
2255
  // This ensures the highest seed value wins in case of concurrent operations
2101
2256
  await dbConnection
2102
2257
  .collection(FIELD_SEQUENCES_COLLECTION)
2103
2258
  .findOneAndUpdate({ collection, field }, {
2104
2259
  $max: { lastSeqNum: seedValue },
2105
- $setOnInsert: { collection, field }
2106
- }, { upsert: true, returnDocument: 'after', ...this._sessionOpt() });
2260
+ $setOnInsert: { collection, field },
2261
+ }, { upsert: true, returnDocument: "after", ...this._sessionOpt() });
2107
2262
  // Now increment atomically to get next value
2108
2263
  const updated = await dbConnection
2109
2264
  .collection(FIELD_SEQUENCES_COLLECTION)
2110
- .findOneAndUpdate({ collection, field }, { $inc: { lastSeqNum: 1 } }, { returnDocument: 'after', ...this._sessionOpt() });
2265
+ .findOneAndUpdate({ collection, field }, { $inc: { lastSeqNum: 1 } }, { returnDocument: "after", ...this._sessionOpt() });
2111
2266
  return updated.lastSeqNum;
2112
2267
  }
2113
2268
  // Sequence exists - check if collection was cleared (reset scenario)
@@ -2120,7 +2275,7 @@ export class Mongo extends Db {
2120
2275
  // Increment and return
2121
2276
  const result = await dbConnection
2122
2277
  .collection(FIELD_SEQUENCES_COLLECTION)
2123
- .findOneAndUpdate({ collection, field }, { $inc: { lastSeqNum: 1 } }, { returnDocument: 'after', ...this._sessionOpt() });
2278
+ .findOneAndUpdate({ collection, field }, { $inc: { lastSeqNum: 1 } }, { returnDocument: "after", ...this._sessionOpt() });
2124
2279
  return result.lastSeqNum;
2125
2280
  }
2126
2281
  /**
@@ -2169,14 +2324,14 @@ export class Mongo extends Db {
2169
2324
  if (!existingSeq) {
2170
2325
  // First time for this collection/field - ensure index exists
2171
2326
  await this._ensureSequencesIndex(dbConnection);
2172
- const seedValue = (existingMax !== undefined && existingMax >= 1) ? existingMax : 0;
2327
+ const seedValue = existingMax !== undefined && existingMax >= 1 ? existingMax : 0;
2173
2328
  // Use $max to handle concurrent seeding
2174
2329
  await dbConnection
2175
2330
  .collection(FIELD_SEQUENCES_COLLECTION)
2176
2331
  .findOneAndUpdate({ collection, field }, {
2177
2332
  $max: { lastSeqNum: seedValue },
2178
- $setOnInsert: { collection, field }
2179
- }, { upsert: true, returnDocument: 'after', ...this._sessionOpt() });
2333
+ $setOnInsert: { collection, field },
2334
+ }, { upsert: true, returnDocument: "after", ...this._sessionOpt() });
2180
2335
  }
2181
2336
  else if (existingMax === undefined && existingSeq.lastSeqNum > 0) {
2182
2337
  // Collection is empty but we have a non-zero sequence - reset to 0
@@ -2187,7 +2342,7 @@ export class Mongo extends Db {
2187
2342
  // Now atomically reserve the range
2188
2343
  const result = await dbConnection
2189
2344
  .collection(FIELD_SEQUENCES_COLLECTION)
2190
- .findOneAndUpdate({ collection, field }, { $inc: { lastSeqNum: count } }, { returnDocument: 'after', ...this._sessionOpt() });
2345
+ .findOneAndUpdate({ collection, field }, { $inc: { lastSeqNum: count } }, { returnDocument: "after", ...this._sessionOpt() });
2191
2346
  const end = result.lastSeqNum;
2192
2347
  return { start: end - count + 1, end };
2193
2348
  }
@@ -2212,17 +2367,20 @@ export class Mongo extends Db {
2212
2367
  return;
2213
2368
  if (!this._hasSequenceFields(object) && !this.syncSupport)
2214
2369
  return;
2215
- const seqKeys = Object.keys(object).filter(key => object[key] === 'SEQ_NEXT' || object[key] === 'SEQ_LAST');
2370
+ const seqKeys = Object.keys(object).filter((key) => object[key] === "SEQ_NEXT" ||
2371
+ object[key] === "SEQ_LAST");
2216
2372
  return { seqKeys };
2217
2373
  }
2218
2374
  async _processSequenceField(client, dbName, collection, insert, seqKeys) {
2219
- assert(this.client, "client is required", "_processSequenceField", { collection });
2375
+ assert(this.client, "client is required", "_processSequenceField", {
2376
+ collection,
2377
+ });
2220
2378
  // if (this.syncSupport) {
2221
2379
  // insert._csq = (await this._getNextCollectionUpdateSeqNo(collection, client));
2222
2380
  // }
2223
2381
  const db = client.db(dbName);
2224
2382
  for (const seqKey of (seqKeys === null || seqKeys === void 0 ? void 0 : seqKeys.seqKeys) || []) {
2225
- if (insert[seqKey] === 'SEQ_LAST') {
2383
+ if (insert[seqKey] === "SEQ_LAST") {
2226
2384
  insert[seqKey] = await this._getLastSequenceValue(db, collection, seqKey);
2227
2385
  }
2228
2386
  else {
@@ -2232,7 +2390,9 @@ export class Mongo extends Db {
2232
2390
  return insert;
2233
2391
  }
2234
2392
  async _processSequenceFieldForMany(connection, dbName, collection, inserts) {
2235
- assert(this.client, "client is required", "_processSequenceFieldForMany", { collection });
2393
+ assert(this.client, "client is required", "_processSequenceFieldForMany", {
2394
+ collection,
2395
+ });
2236
2396
  assert(connection, "connection is required", "_processSequenceFieldForMany", { collection });
2237
2397
  if (!(inserts === null || inserts === void 0 ? void 0 : inserts.length))
2238
2398
  return;
@@ -2240,7 +2400,7 @@ export class Mongo extends Db {
2240
2400
  let seqKeysSet = new Set();
2241
2401
  for (let insert of inserts) {
2242
2402
  let spec = this._findSequenceKeys(insert);
2243
- spec === null || spec === void 0 ? void 0 : spec.seqKeys.forEach(key => seqKeysSet.add(key));
2403
+ spec === null || spec === void 0 ? void 0 : spec.seqKeys.forEach((key) => seqKeysSet.add(key));
2244
2404
  }
2245
2405
  let seqKeys = Array.from(seqKeysSet);
2246
2406
  if (!seqKeys.length)
@@ -2251,7 +2411,7 @@ export class Mongo extends Db {
2251
2411
  // Count SEQ_NEXT occurrences to reserve the range
2252
2412
  let seqNextCount = 0;
2253
2413
  for (const insert of inserts) {
2254
- if (insert[seqKey] === 'SEQ_NEXT')
2414
+ if (insert[seqKey] === "SEQ_NEXT")
2255
2415
  seqNextCount++;
2256
2416
  }
2257
2417
  // Get current value and reserve range for SEQ_NEXT if needed
@@ -2268,10 +2428,10 @@ export class Mongo extends Db {
2268
2428
  // Process inserts in order - SEQ_LAST gets current, SEQ_NEXT increments and gets new value
2269
2429
  for (const insert of inserts) {
2270
2430
  const val = insert[seqKey];
2271
- if (val === 'SEQ_LAST') {
2431
+ if (val === "SEQ_LAST") {
2272
2432
  insert[seqKey] = currentValue;
2273
2433
  }
2274
- else if (val === 'SEQ_NEXT') {
2434
+ else if (val === "SEQ_NEXT") {
2275
2435
  currentValue++;
2276
2436
  insert[seqKey] = currentValue;
2277
2437
  }
@@ -2282,9 +2442,13 @@ export class Mongo extends Db {
2282
2442
  _getFieldsRecursively(obj, into = []) {
2283
2443
  for (let key in obj) {
2284
2444
  const isDollarKey = startsWithDollar(key);
2285
- if (isDollarKey && typeof obj[key] === "object" && !Array.isArray(obj[key]))
2445
+ if (isDollarKey &&
2446
+ typeof obj[key] === "object" &&
2447
+ !Array.isArray(obj[key]))
2286
2448
  this._getFieldsRecursively(obj[key], into);
2287
- else if (!isDollarKey && typeof obj[key] === "object" && !Array.isArray(obj[key]))
2449
+ else if (!isDollarKey &&
2450
+ typeof obj[key] === "object" &&
2451
+ !Array.isArray(obj[key]))
2288
2452
  into.push(key);
2289
2453
  else if (!isDollarKey)
2290
2454
  into.push(key);
@@ -2314,7 +2478,7 @@ export class Mongo extends Db {
2314
2478
  const out = {};
2315
2479
  const keys = this._getFieldsRecursively(inputUpdate);
2316
2480
  for (const k of keys) {
2317
- const bracketIdx = k.indexOf('[');
2481
+ const bracketIdx = k.indexOf("[");
2318
2482
  if (bracketIdx < 0) {
2319
2483
  out[k] = wholerecord[k];
2320
2484
  continue;
@@ -2322,7 +2486,7 @@ export class Mongo extends Db {
2322
2486
  // Bracket path: publish the top-level parent field as a whole,
2323
2487
  // sliced from the post-update document. The "top-level parent" is
2324
2488
  // everything before the FIRST `.` or `[` separator.
2325
- const dotIdx = k.indexOf('.');
2489
+ const dotIdx = k.indexOf(".");
2326
2490
  const cutAt = dotIdx >= 0 && dotIdx < bracketIdx ? dotIdx : bracketIdx;
2327
2491
  const topField = k.substring(0, cutAt);
2328
2492
  if (topField && !(topField in out))
@@ -2351,7 +2515,7 @@ export class Mongo extends Db {
2351
2515
  if (!this.auditing)
2352
2516
  return false;
2353
2517
  const fullName = ((db ? db + "." : "") + (col || "")).toLowerCase();
2354
- return this.auditedCollectionsLower.some(m => fullName.includes(m));
2518
+ return this.auditedCollectionsLower.some((m) => fullName.includes(m));
2355
2519
  }
2356
2520
  async _publishAndAudit(operation, db, collection, dataToPublish, noEmit, rawUpdate) {
2357
2521
  if (!dataToPublish._id && !["deleteMany", "updateMany"].includes(operation))
@@ -2383,7 +2547,7 @@ export class Mongo extends Db {
2383
2547
  }
2384
2548
  }
2385
2549
  if (this._shouldAuditCollection(db, collection)) {
2386
- if (['insert', 'update', 'delete'].includes(operation))
2550
+ if (["insert", "update", "delete"].includes(operation))
2387
2551
  await this._writeAuditRecord(db, collection, operation, data);
2388
2552
  }
2389
2553
  return toPublishAll;
@@ -2411,11 +2575,11 @@ export class Mongo extends Db {
2411
2575
  const user = (_a = data === null || data === void 0 ? void 0 : data._auth) === null || _a === void 0 ? void 0 : _a.username;
2412
2576
  let toPublish;
2413
2577
  switch (operation) {
2414
- case 'insert':
2578
+ case "insert":
2415
2579
  toPublish = {
2416
2580
  channel,
2417
2581
  payload: {
2418
- operation: 'insert',
2582
+ operation: "insert",
2419
2583
  db,
2420
2584
  collection,
2421
2585
  _id: data._id,
@@ -2425,11 +2589,11 @@ export class Mongo extends Db {
2425
2589
  },
2426
2590
  };
2427
2591
  break;
2428
- case 'update':
2592
+ case "update":
2429
2593
  toPublish = {
2430
2594
  channel,
2431
2595
  payload: {
2432
- operation: 'update',
2596
+ operation: "update",
2433
2597
  db,
2434
2598
  collection,
2435
2599
  _id: data._id,
@@ -2439,11 +2603,11 @@ export class Mongo extends Db {
2439
2603
  },
2440
2604
  };
2441
2605
  break;
2442
- case 'delete':
2606
+ case "delete":
2443
2607
  toPublish = {
2444
2608
  channel,
2445
2609
  payload: {
2446
- operation: 'delete',
2610
+ operation: "delete",
2447
2611
  db,
2448
2612
  collection,
2449
2613
  _id: data._id,
@@ -2453,30 +2617,30 @@ export class Mongo extends Db {
2453
2617
  },
2454
2618
  };
2455
2619
  break;
2456
- case 'updateMany':
2620
+ case "updateMany":
2457
2621
  toPublish = {
2458
2622
  channel,
2459
2623
  payload: {
2460
- operation: 'updateMany',
2624
+ operation: "updateMany",
2461
2625
  db,
2462
2626
  collection,
2463
2627
  enquireLastTs: true,
2464
2628
  },
2465
2629
  };
2466
2630
  break;
2467
- case 'deleteMany':
2631
+ case "deleteMany":
2468
2632
  toPublish = {
2469
2633
  channel,
2470
2634
  payload: {
2471
- operation: 'deleteMany',
2635
+ operation: "deleteMany",
2472
2636
  db,
2473
2637
  collection,
2474
2638
  enquireLastTs: true,
2475
2639
  },
2476
2640
  };
2477
2641
  break;
2478
- case 'batch':
2479
- throw new Error('batch operation should use direct emit, not _makeRevPublication');
2642
+ case "batch":
2643
+ throw new Error("batch operation should use direct emit, not _makeRevPublication");
2480
2644
  }
2481
2645
  if (user)
2482
2646
  toPublish.user = user;
@@ -2493,12 +2657,17 @@ export class Mongo extends Db {
2493
2657
  if (!this.auditing)
2494
2658
  return;
2495
2659
  let client = await this.connect();
2496
- let previousAuditRecords = await (await client.db(db).collection(this.auditCollectionName).aggregate([
2660
+ let previousAuditRecords = await (await client
2661
+ .db(db)
2662
+ .collection(this.auditCollectionName)
2663
+ .aggregate([
2497
2664
  { $match: { entityid: Mongo._toId(data._id) } },
2498
2665
  { $sort: { rev: -1 } },
2499
- { $limit: 1 }
2666
+ { $limit: 1 },
2500
2667
  ], this.session ? { session: this.session } : {})).toArray();
2501
- let previousAuditRecord = previousAuditRecords.length ? previousAuditRecords[0] : { rev: 0, changes: {} };
2668
+ let previousAuditRecord = previousAuditRecords.length
2669
+ ? previousAuditRecords[0]
2670
+ : { rev: 0, changes: {} };
2502
2671
  if (previousAuditRecords.length === 0)
2503
2672
  await this.createCollection(this.auditCollectionName);
2504
2673
  let dataNoId = { ...data };
@@ -2517,11 +2686,12 @@ export class Mongo extends Db {
2517
2686
  auditRecord.user = user;
2518
2687
  if (audit)
2519
2688
  auditRecord.audit = audit;
2520
- fjLog.trace('AUDITING', auditRecord);
2521
- let ret = await client.db(db)
2689
+ fjLog.trace("AUDITING", auditRecord);
2690
+ let ret = await client
2691
+ .db(db)
2522
2692
  .collection(this.auditCollectionName)
2523
2693
  .insertOne(auditRecord, this._sessionOpt());
2524
- fjLog.debug('AUDITED', auditRecord, ret.insertedId);
2694
+ fjLog.debug("AUDITED", auditRecord, ret.insertedId);
2525
2695
  }
2526
2696
  _sessionOpt() {
2527
2697
  return this.session ? { session: this.session } : {};
@@ -2552,7 +2722,7 @@ export class Mongo extends Db {
2552
2722
  return Object.keys(obj).some(startsWithHashedPrefix);
2553
2723
  }
2554
2724
  _hasSequenceFields(obj) {
2555
- return Object.values(obj).some(v => v === 'SEQ_NEXT' || v === 'SEQ_LAST');
2725
+ return Object.values(obj).some((v) => v === "SEQ_NEXT" || v === "SEQ_LAST");
2556
2726
  }
2557
2727
  _processUpdateObject(update) {
2558
2728
  for (let k in update) {
@@ -2560,7 +2730,8 @@ export class Mongo extends Db {
2560
2730
  const keyStr = String(key);
2561
2731
  if (keyStr[0] === "$")
2562
2732
  continue;
2563
- if (startsWithDoubleUnderscore(keyStr) && !keyStr.startsWith(HASHED_PREFIX)) {
2733
+ if (startsWithDoubleUnderscore(keyStr) &&
2734
+ !keyStr.startsWith(HASHED_PREFIX)) {
2564
2735
  delete update[key];
2565
2736
  continue;
2566
2737
  }
@@ -2568,7 +2739,7 @@ export class Mongo extends Db {
2568
2739
  delete update[key];
2569
2740
  continue;
2570
2741
  }
2571
- if (key === '' || key === null || key === undefined) {
2742
+ if (key === "" || key === null || key === undefined) {
2572
2743
  delete update[key];
2573
2744
  continue;
2574
2745
  }
@@ -2586,12 +2757,14 @@ export class Mongo extends Db {
2586
2757
  if (this.revisions) {
2587
2758
  update.$inc = update.$inc || {};
2588
2759
  update.$inc._rev = 1;
2589
- const currentDate = update.$currentDate && typeof update.$currentDate === 'object' && !Array.isArray(update.$currentDate)
2760
+ const currentDate = update.$currentDate &&
2761
+ typeof update.$currentDate === "object" &&
2762
+ !Array.isArray(update.$currentDate)
2590
2763
  ? update.$currentDate
2591
2764
  : undefined;
2592
2765
  update.$currentDate = {
2593
2766
  ...(currentDate || {}),
2594
- _ts: { $type: 'timestamp' }
2767
+ _ts: { $type: "timestamp" },
2595
2768
  };
2596
2769
  }
2597
2770
  if (update.$set) {
@@ -2631,35 +2804,41 @@ export class Mongo extends Db {
2631
2804
  const translatePath = (path) => {
2632
2805
  const tokens = Mongo._tokenizePath(path);
2633
2806
  const out = [];
2634
- let parentKey = '';
2807
+ let parentKey = "";
2635
2808
  for (const t of tokens) {
2636
- if (t.length >= 2 && t.charCodeAt(0) === 91 /* [ */ && t.charCodeAt(t.length - 1) === 93 /* ] */) {
2809
+ if (t.length >= 2 &&
2810
+ t.charCodeAt(0) === 91 /* [ */ &&
2811
+ t.charCodeAt(t.length - 1) === 93 /* ] */) {
2637
2812
  const idStr = Mongo._unquoteBracketId(t, path);
2638
2813
  const memoKey = `${parentKey}|${idStr}`;
2639
2814
  let filterName = memo.get(memoKey);
2640
2815
  if (filterName === undefined) {
2641
2816
  filterName = `f${counter++}`;
2642
2817
  memo.set(memoKey, filterName);
2643
- filters.push({ [`${filterName}._id`]: Mongo._normalizeBracketId(idStr) });
2818
+ filters.push({
2819
+ [`${filterName}._id`]: Mongo._normalizeBracketId(idStr),
2820
+ });
2644
2821
  }
2645
2822
  out.push(`$[${filterName}]`);
2646
- parentKey = parentKey ? `${parentKey}.$[${filterName}]` : `$[${filterName}]`;
2823
+ parentKey = parentKey
2824
+ ? `${parentKey}.$[${filterName}]`
2825
+ : `$[${filterName}]`;
2647
2826
  }
2648
2827
  else {
2649
2828
  out.push(t);
2650
2829
  parentKey = parentKey ? `${parentKey}.${t}` : t;
2651
2830
  }
2652
2831
  }
2653
- return out.join('.');
2832
+ return out.join(".");
2654
2833
  };
2655
2834
  const translateOp = (opName) => {
2656
2835
  const op = update[opName];
2657
- if (!op || typeof op !== 'object')
2836
+ if (!op || typeof op !== "object")
2658
2837
  return;
2659
2838
  // Fast path: skip rebuild if no bracket present.
2660
2839
  let hasBracket = false;
2661
2840
  for (const k of Object.keys(op)) {
2662
- if (k.indexOf('[') >= 0) {
2841
+ if (k.indexOf("[") >= 0) {
2663
2842
  hasBracket = true;
2664
2843
  break;
2665
2844
  }
@@ -2672,8 +2851,8 @@ export class Mongo extends Db {
2672
2851
  }
2673
2852
  update[opName] = translated;
2674
2853
  };
2675
- translateOp('$set');
2676
- translateOp('$unset');
2854
+ translateOp("$set");
2855
+ translateOp("$unset");
2677
2856
  return filters.length > 0 ? filters : undefined;
2678
2857
  }
2679
2858
  /**
@@ -2723,38 +2902,38 @@ export class Mongo extends Db {
2723
2902
  var _a;
2724
2903
  if (value === null || value === undefined)
2725
2904
  return false;
2726
- if (typeof value !== 'object')
2905
+ if (typeof value !== "object")
2727
2906
  return false;
2728
2907
  if (value instanceof Date)
2729
2908
  return false;
2730
2909
  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')
2910
+ if (ctorName === "ObjectId" ||
2911
+ ctorName === "Timestamp" ||
2912
+ ctorName === "Decimal128" ||
2913
+ ctorName === "Binary" ||
2914
+ ctorName === "Long" ||
2915
+ ctorName === "Double" ||
2916
+ ctorName === "Int32")
2738
2917
  return false;
2739
2918
  return true;
2740
2919
  }
2741
2920
  static _tokenizePath(path) {
2742
2921
  const out = [];
2743
- let buf = '';
2922
+ let buf = "";
2744
2923
  for (let i = 0; i < path.length; i++) {
2745
2924
  const ch = path[i];
2746
- if (ch === '.') {
2925
+ if (ch === ".") {
2747
2926
  if (buf) {
2748
2927
  out.push(buf);
2749
- buf = '';
2928
+ buf = "";
2750
2929
  }
2751
2930
  }
2752
- else if (ch === '[') {
2931
+ else if (ch === "[") {
2753
2932
  if (buf) {
2754
2933
  out.push(buf);
2755
- buf = '';
2934
+ buf = "";
2756
2935
  }
2757
- const close = path.indexOf(']', i);
2936
+ const close = path.indexOf("]", i);
2758
2937
  if (close < 0) {
2759
2938
  buf += ch;
2760
2939
  continue;
@@ -2786,7 +2965,8 @@ export class Mongo extends Db {
2786
2965
  if (len >= 2) {
2787
2966
  const first = id.charCodeAt(0);
2788
2967
  const last = id.charCodeAt(len - 1);
2789
- if ((first === 39 /* ' */ && last === 39) || (first === 34 /* " */ && last === 34)) {
2968
+ if ((first === 39 /* ' */ && last === 39) ||
2969
+ (first === 34 /* " */ && last === 34)) {
2790
2970
  id = id.slice(1, -1);
2791
2971
  }
2792
2972
  }
@@ -2818,11 +2998,11 @@ export class Mongo extends Db {
2818
2998
  */
2819
2999
  _validateAndAutoFillTerminalBracketValues(update) {
2820
3000
  const $set = update.$set;
2821
- if (!$set || typeof $set !== 'object')
3001
+ if (!$set || typeof $set !== "object")
2822
3002
  return;
2823
3003
  let hasBracket = false;
2824
3004
  for (const k of Object.keys($set)) {
2825
- if (k.indexOf('[') >= 0) {
3005
+ if (k.indexOf("[") >= 0) {
2826
3006
  hasBracket = true;
2827
3007
  break;
2828
3008
  }
@@ -2832,17 +3012,17 @@ export class Mongo extends Db {
2832
3012
  for (const path of Object.keys($set)) {
2833
3013
  const tokens = Mongo._tokenizePath(path);
2834
3014
  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 /* ] */);
3015
+ const isTerminalBracket = !!((lastToken &&
3016
+ lastToken.length >= 2 &&
3017
+ lastToken.charCodeAt(0) === 91 /* [ */ &&
3018
+ lastToken.charCodeAt(lastToken.length - 1) === 93) /* ] */);
2839
3019
  if (!isTerminalBracket)
2840
3020
  continue;
2841
3021
  const bracketId = Mongo._unquoteBracketId(lastToken, path); // throws on empty
2842
3022
  const value = $set[path];
2843
3023
  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}).`);
3024
+ if (el == null || typeof el !== "object") {
3025
+ 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
3026
  }
2847
3027
  if (el._id == null) {
2848
3028
  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 +3035,10 @@ export class Mongo extends Db {
2855
3035
  for (let i = 0; i < value.length; i++)
2856
3036
  validateElement(value[i], ` [${i}]`);
2857
3037
  }
2858
- else if (value !== null && value !== undefined && typeof value === 'object') {
2859
- validateElement(value, '');
3038
+ else if (value !== null &&
3039
+ value !== undefined &&
3040
+ typeof value === "object") {
3041
+ validateElement(value, "");
2860
3042
  }
2861
3043
  // Primitives (string/number/boolean) — pass through to existing arrayFilters
2862
3044
  // path. Mongo would set the array element to the primitive, which is unusual
@@ -2887,12 +3069,12 @@ export class Mongo extends Db {
2887
3069
  */
2888
3070
  _extractArrayInserts(update) {
2889
3071
  const $set = update.$set;
2890
- if (!$set || typeof $set !== 'object')
3072
+ if (!$set || typeof $set !== "object")
2891
3073
  return undefined;
2892
3074
  // Fast path: no bracket present in any key.
2893
3075
  let hasBracket = false;
2894
3076
  for (const k of Object.keys($set)) {
2895
- if (k.indexOf('[') >= 0) {
3077
+ if (k.indexOf("[") >= 0) {
2896
3078
  hasBracket = true;
2897
3079
  break;
2898
3080
  }
@@ -2905,19 +3087,19 @@ export class Mongo extends Db {
2905
3087
  const value = $set[path];
2906
3088
  const tokens = Mongo._tokenizePath(path);
2907
3089
  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 /* ] */);
3090
+ const isTerminalBracket = !!((lastToken &&
3091
+ lastToken.length >= 2 &&
3092
+ lastToken.charCodeAt(0) === 91 /* [ */ &&
3093
+ lastToken.charCodeAt(lastToken.length - 1) === 93) /* ] */);
2912
3094
  if (isTerminalBracket && Array.isArray(value)) {
2913
3095
  const parentTokens = tokens.slice(0, -1);
2914
3096
  // Reject nested-bracket parent paths — combining $push semantics with
2915
3097
  // arrayFilters-targeted parent is not cleanly expressible in mongo.
2916
3098
  const parentHasBracket = parentTokens.some((t) => t.length > 0 && t.charCodeAt(0) === 91);
2917
3099
  // 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);
3100
+ const allElementsHaveId = value.every((e) => e && typeof e === "object" && e._id != null);
2919
3101
  if (!parentHasBracket && allElementsHaveId && parentTokens.length > 0) {
2920
- const fieldPath = parentTokens.join('.');
3102
+ const fieldPath = parentTokens.join(".");
2921
3103
  const ids = value.map((e) => String(e._id));
2922
3104
  inserts.push({ field: fieldPath, ids, elements: value });
2923
3105
  continue;
@@ -2954,11 +3136,11 @@ export class Mongo extends Db {
2954
3136
  */
2955
3137
  _extractArrayRemoves(update) {
2956
3138
  const $unset = update.$unset;
2957
- if (!$unset || typeof $unset !== 'object')
3139
+ if (!$unset || typeof $unset !== "object")
2958
3140
  return undefined;
2959
3141
  let hasBracket = false;
2960
3142
  for (const k of Object.keys($unset)) {
2961
- if (k.indexOf('[') >= 0) {
3143
+ if (k.indexOf("[") >= 0) {
2962
3144
  hasBracket = true;
2963
3145
  break;
2964
3146
  }
@@ -2970,15 +3152,15 @@ export class Mongo extends Db {
2970
3152
  for (const path of Object.keys($unset)) {
2971
3153
  const tokens = Mongo._tokenizePath(path);
2972
3154
  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 /* ] */);
3155
+ const isTerminalBracket = !!((lastToken &&
3156
+ lastToken.length >= 2 &&
3157
+ lastToken.charCodeAt(0) === 91 /* [ */ &&
3158
+ lastToken.charCodeAt(lastToken.length - 1) === 93) /* ] */);
2977
3159
  if (isTerminalBracket) {
2978
3160
  const parentTokens = tokens.slice(0, -1);
2979
3161
  const parentHasBracket = parentTokens.some((t) => t.length > 0 && t.charCodeAt(0) === 91);
2980
3162
  if (!parentHasBracket && parentTokens.length > 0) {
2981
- const fieldPath = parentTokens.join('.');
3163
+ const fieldPath = parentTokens.join(".");
2982
3164
  const id = Mongo._unquoteBracketId(lastToken, path);
2983
3165
  if (!removesByField.has(fieldPath))
2984
3166
  removesByField.set(fieldPath, []);
@@ -2993,7 +3175,10 @@ export class Mongo extends Db {
2993
3175
  update.$unset = remaining;
2994
3176
  if (Object.keys(remaining).length === 0)
2995
3177
  delete update.$unset;
2996
- return Array.from(removesByField.entries()).map(([field, ids]) => ({ field, ids }));
3178
+ return Array.from(removesByField.entries()).map(([field, ids]) => ({
3179
+ field,
3180
+ ids,
3181
+ }));
2997
3182
  }
2998
3183
  /**
2999
3184
  * Extracts SINGLE-bracket bracket-by-_id paths from `$set`/`$unset`, grouped
@@ -3029,11 +3214,11 @@ export class Mongo extends Db {
3029
3214
  };
3030
3215
  const processOp = (opName) => {
3031
3216
  const op = update[opName];
3032
- if (!op || typeof op !== 'object')
3217
+ if (!op || typeof op !== "object")
3033
3218
  return;
3034
3219
  let hasBracket = false;
3035
3220
  for (const k of Object.keys(op)) {
3036
- if (k.indexOf('[') >= 0) {
3221
+ if (k.indexOf("[") >= 0) {
3037
3222
  hasBracket = true;
3038
3223
  break;
3039
3224
  }
@@ -3048,18 +3233,20 @@ export class Mongo extends Db {
3048
3233
  let bracketIdx = -1;
3049
3234
  for (let i = 0; i < tokens.length; i++) {
3050
3235
  const t = tokens[i];
3051
- if (t.length >= 2 && t.charCodeAt(0) === 91 /* [ */ && t.charCodeAt(t.length - 1) === 93 /* ] */) {
3236
+ if (t.length >= 2 &&
3237
+ t.charCodeAt(0) === 91 /* [ */ &&
3238
+ t.charCodeAt(t.length - 1) === 93 /* ] */) {
3052
3239
  bracketCount++;
3053
3240
  bracketIdx = i;
3054
3241
  }
3055
3242
  }
3056
3243
  if (bracketCount === 1 && bracketIdx > 0) {
3057
- const parentField = tokens.slice(0, bracketIdx).join('.');
3244
+ const parentField = tokens.slice(0, bracketIdx).join(".");
3058
3245
  const id = Mongo._unquoteBracketId(tokens[bracketIdx], path);
3059
- const restPath = tokens.slice(bracketIdx + 1).join('.');
3246
+ const restPath = tokens.slice(bracketIdx + 1).join(".");
3060
3247
  const elOps = ensureEntry(parentField, id);
3061
- if (opName === '$set') {
3062
- if (restPath === '') {
3248
+ if (opName === "$set") {
3249
+ if (restPath === "") {
3063
3250
  // `arr[id]: <obj>` — whole-element replace.
3064
3251
  elOps.replace = op[path];
3065
3252
  }
@@ -3070,7 +3257,7 @@ export class Mongo extends Db {
3070
3257
  else {
3071
3258
  // `$unset arr[id].field` — sub-field unset. Terminal `$unset arr[id]`
3072
3259
  // is already extracted by `_extractArrayRemoves`.
3073
- if (restPath === '') {
3260
+ if (restPath === "") {
3074
3261
  remaining[path] = op[path];
3075
3262
  continue;
3076
3263
  }
@@ -3088,8 +3275,8 @@ export class Mongo extends Db {
3088
3275
  delete update[opName];
3089
3276
  }
3090
3277
  };
3091
- processOp('$set');
3092
- processOp('$unset');
3278
+ processOp("$set");
3279
+ processOp("$unset");
3093
3280
  return extractedAny ? result : undefined;
3094
3281
  }
3095
3282
  /**
@@ -3108,8 +3295,8 @@ export class Mongo extends Db {
3108
3295
  const filteredInput = {
3109
3296
  $filter: {
3110
3297
  input: { $ifNull: [baseInputPath, []] },
3111
- as: 'el',
3112
- cond: { $not: { $in: ['$$el._id', dedupedRemoveIds] } },
3298
+ as: "el",
3299
+ cond: { $not: { $in: ["$$el._id", dedupedRemoveIds] } },
3113
3300
  },
3114
3301
  };
3115
3302
  const concatExpr = {
@@ -3120,15 +3307,15 @@ export class Mongo extends Db {
3120
3307
  const branches = [];
3121
3308
  for (const [id, elOps] of ops.elementOps.entries()) {
3122
3309
  branches.push({
3123
- case: { $eq: ['$$el._id', Mongo._normalizeBracketId(id)] },
3124
- then: Mongo._buildElementMergeExpr('$$el', elOps),
3310
+ case: { $eq: ["$$el._id", Mongo._normalizeBracketId(id)] },
3311
+ then: Mongo._buildElementMergeExpr("$$el", elOps),
3125
3312
  });
3126
3313
  }
3127
3314
  return {
3128
3315
  $map: {
3129
3316
  input: concatExpr,
3130
- as: 'el',
3131
- in: { $switch: { branches, default: '$$el' } },
3317
+ as: "el",
3318
+ in: { $switch: { branches, default: "$$el" } },
3132
3319
  },
3133
3320
  };
3134
3321
  }
@@ -3211,13 +3398,13 @@ export class Mongo extends Db {
3211
3398
  return {
3212
3399
  $let: {
3213
3400
  vars: { replaced: replaceExpr },
3214
- in: wrapWithNestedArrays('$$replaced', '$$replaced'),
3401
+ in: wrapWithNestedArrays("$$replaced", "$$replaced"),
3215
3402
  },
3216
3403
  };
3217
3404
  }
3218
3405
  const root = { directs: {}, nested: {}, unsets: [] };
3219
3406
  const walkInsert = (path, isUnset, value) => {
3220
- const parts = path.split('.');
3407
+ const parts = path.split(".");
3221
3408
  let node = root;
3222
3409
  for (let i = 0; i < parts.length - 1; i++) {
3223
3410
  const key = parts[i];
@@ -3255,15 +3442,17 @@ export class Mongo extends Db {
3255
3442
  overlay[k] = buildOverlay(sub, subPath);
3256
3443
  }
3257
3444
  // Merge sets/nested onto the existing object (or {} if absent).
3258
- let merged = { $mergeObjects: [{ $ifNull: [basePath, {}] }, overlay] };
3445
+ let merged = {
3446
+ $mergeObjects: [{ $ifNull: [basePath, {}] }, overlay],
3447
+ };
3259
3448
  // Drop unset top-level keys at this level via kv-filter.
3260
3449
  if (node.unsets.length > 0) {
3261
3450
  merged = {
3262
3451
  $arrayToObject: {
3263
3452
  $filter: {
3264
3453
  input: { $objectToArray: merged },
3265
- as: 'kv',
3266
- cond: { $not: { $in: ['$$kv.k', node.unsets] } },
3454
+ as: "kv",
3455
+ cond: { $not: { $in: ["$$kv.k", node.unsets] } },
3267
3456
  },
3268
3457
  },
3269
3458
  };
@@ -3273,11 +3462,11 @@ export class Mongo extends Db {
3273
3462
  // If a replace is also requested, treat replacement as the new base.
3274
3463
  // Wrap with `$let` since a literal object isn't addressable by string field path.
3275
3464
  if (hasReplace) {
3276
- const overlayExpr = buildOverlay(root, '$$replaced');
3465
+ const overlayExpr = buildOverlay(root, "$$replaced");
3277
3466
  return {
3278
3467
  $let: {
3279
3468
  vars: { replaced: { $literal: ops.replace } },
3280
- in: wrapWithNestedArrays(overlayExpr, '$$replaced'),
3469
+ in: wrapWithNestedArrays(overlayExpr, "$$replaced"),
3281
3470
  },
3282
3471
  };
3283
3472
  }
@@ -3298,7 +3487,7 @@ export class Mongo extends Db {
3298
3487
  static _drainIncAndCurrentDateToPipelineStages(update) {
3299
3488
  const stages = [];
3300
3489
  const inc = update.$inc;
3301
- if (inc && typeof inc === 'object') {
3490
+ if (inc && typeof inc === "object") {
3302
3491
  const setObj = {};
3303
3492
  for (const [k, v] of Object.entries(inc)) {
3304
3493
  setObj[k] = { $add: [{ $ifNull: [`$${k}`, 0] }, v] };
@@ -3308,13 +3497,15 @@ export class Mongo extends Db {
3308
3497
  delete update.$inc;
3309
3498
  }
3310
3499
  const cd = update.$currentDate;
3311
- if (cd && typeof cd === 'object') {
3500
+ if (cd && typeof cd === "object") {
3312
3501
  const setObj = {};
3313
3502
  for (const [k, spec] of Object.entries(cd)) {
3314
3503
  let isTimestamp = false;
3315
- if (spec && typeof spec === 'object' && spec.$type === 'timestamp')
3504
+ if (spec &&
3505
+ typeof spec === "object" &&
3506
+ spec.$type === "timestamp")
3316
3507
  isTimestamp = true;
3317
- setObj[k] = isTimestamp ? '$$CLUSTER_TIME' : '$$NOW';
3508
+ setObj[k] = isTimestamp ? "$$CLUSTER_TIME" : "$$NOW";
3318
3509
  }
3319
3510
  if (Object.keys(setObj).length > 0)
3320
3511
  stages.push({ $set: setObj });
@@ -3370,14 +3561,18 @@ export class Mongo extends Db {
3370
3561
  continue;
3371
3562
  let bracketCount = 0;
3372
3563
  for (const t of tokens) {
3373
- if (t.length >= 2 && t.charCodeAt(0) === 91 && t.charCodeAt(t.length - 1) === 93) {
3564
+ if (t.length >= 2 &&
3565
+ t.charCodeAt(0) === 91 &&
3566
+ t.charCodeAt(t.length - 1) === 93) {
3374
3567
  bracketCount++;
3375
3568
  }
3376
3569
  }
3377
3570
  if (bracketCount < 2)
3378
3571
  continue;
3379
3572
  const last = tokens[tokens.length - 1];
3380
- if (last.length >= 2 && last.charCodeAt(0) === 91 && last.charCodeAt(last.length - 1) === 93) {
3573
+ if (last.length >= 2 &&
3574
+ last.charCodeAt(0) === 91 &&
3575
+ last.charCodeAt(last.length - 1) === 93) {
3381
3576
  return true;
3382
3577
  }
3383
3578
  }
@@ -3385,13 +3580,51 @@ export class Mongo extends Db {
3385
3580
  };
3386
3581
  const $setEarlyForNested = update.$set;
3387
3582
  const $unsetEarlyForNested = update.$unset;
3388
- const hasNestedTerminal = hasNestedTerminalBracket($setEarlyForNested) || hasNestedTerminalBracket($unsetEarlyForNested);
3583
+ const hasNestedTerminal = hasNestedTerminalBracket($setEarlyForNested) ||
3584
+ hasNestedTerminalBracket($unsetEarlyForNested);
3389
3585
  // Pure sub-field updates only (no inserts, no removes, no nested-terminal) —
3390
3586
  // keep on legacy arrayFilters path (faster, smaller payload, doesn't fight
3391
3587
  // $inc/$currentDate). Nested sub-field paths like `arr[A].sub[B].field`
3392
3588
  // ARE supported via nested arrayFilters here.
3393
3589
  if (!inserts && !removes && !hasNestedTerminal) {
3394
3590
  const arrayFilters = this._extractArrayFilters(update);
3591
+ // Detect conflict: bare-field `$set` with array value alongside a
3592
+ // bracket-transformed sub-path on the same field (`postavke: [...]` +
3593
+ // `postavke.$[f0].nbc`). MongoDB silently drops the sub-field update
3594
+ // in this case — throw so the caller gets an error instead of data loss.
3595
+ if (arrayFilters) {
3596
+ // Collect bare-field array keys and sub-paths from BOTH
3597
+ // $set AND $unset — $set.postavke conflicts with both
3598
+ // $set.postavke.$[f0].nbc AND $unset.postavke.$[f0].nbc.
3599
+ const $setCheck = update.$set;
3600
+ const $unsetCheck = update.$unset;
3601
+ const bareFields = [];
3602
+ const subPaths = [];
3603
+ if ($setCheck) {
3604
+ for (const k of Object.keys($setCheck)) {
3605
+ (k.includes(".") || k.includes("[") ? subPaths : bareFields).push(k);
3606
+ }
3607
+ }
3608
+ if ($unsetCheck) {
3609
+ for (const k of Object.keys($unsetCheck)) {
3610
+ (k.includes(".") || k.includes("[") ? subPaths : bareFields).push(k);
3611
+ }
3612
+ }
3613
+ for (const bare of bareFields) {
3614
+ // Only $set bare fields with array values cause conflicts.
3615
+ if ($setCheck && Array.isArray($setCheck[bare])) {
3616
+ for (const sub of subPaths) {
3617
+ if (sub.startsWith(bare + ".") || sub.startsWith(bare + "[")) {
3618
+ throw new Error(`cry-db: bare-field array replacement "${bare}" conflicts ` +
3619
+ `with bracket-by-_id sub-field path "${sub}" on the same ` +
3620
+ `array. Replace the bare-field assignment with a ` +
3621
+ `terminal-bracket form (e.g. \`${bare}[<id>]: [...]\`) ` +
3622
+ `when combining array updates with bracket-by-_id paths.`);
3623
+ }
3624
+ }
3625
+ }
3626
+ }
3627
+ }
3395
3628
  return arrayFilters ? { update, arrayFilters } : { update };
3396
3629
  }
3397
3630
  // Removes-only fast path: `$pull` on update doc. Coexists fine with `$set` on
@@ -3412,15 +3645,14 @@ export class Mongo extends Db {
3412
3645
  for (const k of Object.keys($setEarly)) {
3413
3646
  if (k === field)
3414
3647
  return true;
3415
- if (k.startsWith(field + '.'))
3648
+ if (k.startsWith(field + "."))
3416
3649
  return true;
3417
- if (k.startsWith(field + '['))
3650
+ if (k.startsWith(field + "["))
3418
3651
  return true;
3419
3652
  }
3420
3653
  return false;
3421
3654
  };
3422
- const removesOnlyNoSetConflict = removes && !inserts
3423
- && !removes.some(rm => setTargetsField(rm.field));
3655
+ const removesOnlyNoSetConflict = removes && !inserts && !removes.some((rm) => setTargetsField(rm.field));
3424
3656
  if (removesOnlyNoSetConflict) {
3425
3657
  const pullOp = (update.$pull || {});
3426
3658
  for (const rm of removes) {
@@ -3465,12 +3697,20 @@ export class Mongo extends Db {
3465
3697
  const fieldOps = new Map();
3466
3698
  const ensureField = (container, field) => {
3467
3699
  if (!container.has(field))
3468
- container.set(field, { removeIds: [], insertElements: [], elementOps: new Map() });
3700
+ container.set(field, {
3701
+ removeIds: [],
3702
+ insertElements: [],
3703
+ elementOps: new Map(),
3704
+ });
3469
3705
  return container.get(field);
3470
3706
  };
3471
3707
  const ensureElement = (fops, id) => {
3472
3708
  if (!fops.elementOps.has(id))
3473
- fops.elementOps.set(id, { sets: {}, unsets: [], nestedArrayOps: new Map() });
3709
+ fops.elementOps.set(id, {
3710
+ sets: {},
3711
+ unsets: [],
3712
+ nestedArrayOps: new Map(),
3713
+ });
3474
3714
  const elOps = fops.elementOps.get(id);
3475
3715
  if (!elOps.nestedArrayOps)
3476
3716
  elOps.nestedArrayOps = new Map();
@@ -3514,7 +3754,7 @@ export class Mongo extends Db {
3514
3754
  return;
3515
3755
  const remaining = {};
3516
3756
  for (const path of Object.keys(op)) {
3517
- if (path.indexOf('[') < 0) {
3757
+ if (path.indexOf("[") < 0) {
3518
3758
  remaining[path] = op[path];
3519
3759
  continue;
3520
3760
  }
@@ -3522,14 +3762,16 @@ export class Mongo extends Db {
3522
3762
  const brackets = [];
3523
3763
  for (let i = 0; i < tokens.length; i++) {
3524
3764
  const t = tokens[i];
3525
- if (t.length >= 2 && t.charCodeAt(0) === 91 && t.charCodeAt(t.length - 1) === 93) {
3765
+ if (t.length >= 2 &&
3766
+ t.charCodeAt(0) === 91 &&
3767
+ t.charCodeAt(t.length - 1) === 93) {
3526
3768
  brackets.push({ idx: i, id: Mongo._unquoteBracketId(t, path) });
3527
3769
  }
3528
3770
  }
3529
3771
  if (brackets.length < 2) {
3530
3772
  // Single-bracket: extractors above should have handled it; if it
3531
3773
  // remained, it's malformed (e.g. empty parent). Drop with warning.
3532
- warnings.push({ path, value: op[path], op: opName, kind: 'dropped' });
3774
+ warnings.push({ path, value: op[path], op: opName, kind: "dropped" });
3533
3775
  continue;
3534
3776
  }
3535
3777
  // Walk all but the innermost bracket — descend through nestedArrayOps.
@@ -3538,7 +3780,7 @@ export class Mongo extends Db {
3538
3780
  for (let bi = 0; bi < brackets.length - 1; bi++) {
3539
3781
  const bracket = brackets[bi];
3540
3782
  const fieldStart = bi === 0 ? 0 : brackets[bi - 1].idx + 1;
3541
- const fieldName = tokens.slice(fieldStart, bracket.idx).join('.');
3783
+ const fieldName = tokens.slice(fieldStart, bracket.idx).join(".");
3542
3784
  if (!fieldName) {
3543
3785
  ok = false;
3544
3786
  break;
@@ -3548,21 +3790,21 @@ export class Mongo extends Db {
3548
3790
  currentMap = elOps.nestedArrayOps;
3549
3791
  }
3550
3792
  if (!ok) {
3551
- warnings.push({ path, value: op[path], op: opName, kind: 'dropped' });
3793
+ warnings.push({ path, value: op[path], op: opName, kind: "dropped" });
3552
3794
  continue;
3553
3795
  }
3554
3796
  const lastB = brackets[brackets.length - 1];
3555
3797
  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('.');
3798
+ const innerFieldName = tokens.slice(fieldStart, lastB.idx).join(".");
3799
+ const restPath = tokens.slice(lastB.idx + 1).join(".");
3558
3800
  if (!innerFieldName) {
3559
- warnings.push({ path, value: op[path], op: opName, kind: 'dropped' });
3801
+ warnings.push({ path, value: op[path], op: opName, kind: "dropped" });
3560
3802
  continue;
3561
3803
  }
3562
3804
  const innerFOps = ensureField(currentMap, innerFieldName);
3563
3805
  const value = op[path];
3564
- if (opName === '$set') {
3565
- if (restPath === '') {
3806
+ if (opName === "$set") {
3807
+ if (restPath === "") {
3566
3808
  if (Array.isArray(value)) {
3567
3809
  innerFOps.removeIds.push(lastB.id);
3568
3810
  innerFOps.insertElements.push(...value);
@@ -3580,7 +3822,7 @@ export class Mongo extends Db {
3580
3822
  }
3581
3823
  else {
3582
3824
  // $unset
3583
- if (restPath === '') {
3825
+ if (restPath === "") {
3584
3826
  innerFOps.removeIds.push(lastB.id);
3585
3827
  }
3586
3828
  else {
@@ -3593,8 +3835,8 @@ export class Mongo extends Db {
3593
3835
  if (Object.keys(remaining).length === 0)
3594
3836
  delete update[opName];
3595
3837
  };
3596
- processNestedPaths(update.$set, '$set');
3597
- processNestedPaths(update.$unset, '$unset');
3838
+ processNestedPaths(update.$set, "$set");
3839
+ processNestedPaths(update.$unset, "$unset");
3598
3840
  // Detect same-id overlap at NESTED levels: a "new base" (terminal-array
3599
3841
  // insert OR whole-element replace) targeting the same `_id` as a
3600
3842
  // sub-field set/unset on the same element. Both apply — new base goes
@@ -3614,7 +3856,7 @@ export class Mongo extends Db {
3614
3856
  const detectOverlaps = (container, parentPathRepr) => {
3615
3857
  for (const [field, fops] of container.entries()) {
3616
3858
  const fullField = parentPathRepr ? `${parentPathRepr}.${field}` : field;
3617
- const isNested = parentPathRepr !== '';
3859
+ const isNested = parentPathRepr !== "";
3618
3860
  // Flavor 1: terminal-array insert + sub-field on same id.
3619
3861
  const removeIdSet = new Set(fops.removeIds);
3620
3862
  if (isNested) {
@@ -3622,16 +3864,16 @@ export class Mongo extends Db {
3622
3864
  const elOps = fops.elementOps.get(id);
3623
3865
  if (!elOps)
3624
3866
  continue;
3625
- const hasOps = Object.keys(elOps.sets).length > 0
3626
- || elOps.unsets.length > 0
3627
- || elOps.replace !== undefined;
3867
+ const hasOps = Object.keys(elOps.sets).length > 0 ||
3868
+ elOps.unsets.length > 0 ||
3869
+ elOps.replace !== undefined;
3628
3870
  if (hasOps) {
3629
3871
  const insertedEl = fops.insertElements.find((e) => String(e._id) === id);
3630
3872
  warnings.push({
3631
3873
  path: `${fullField}[${id}]`,
3632
3874
  value: insertedEl,
3633
- op: '$set',
3634
- kind: 'overlap',
3875
+ op: "$set",
3876
+ kind: "overlap",
3635
3877
  });
3636
3878
  }
3637
3879
  }
@@ -3641,14 +3883,13 @@ export class Mongo extends Db {
3641
3883
  for (const [id, elOps] of fops.elementOps.entries()) {
3642
3884
  if (isNested && !removeIdSet.has(id)) {
3643
3885
  const hasReplace = elOps.replace !== undefined;
3644
- const hasSetsOrUnsets = Object.keys(elOps.sets).length > 0
3645
- || elOps.unsets.length > 0;
3886
+ const hasSetsOrUnsets = Object.keys(elOps.sets).length > 0 || elOps.unsets.length > 0;
3646
3887
  if (hasReplace && hasSetsOrUnsets) {
3647
3888
  warnings.push({
3648
3889
  path: `${fullField}[${id}]`,
3649
3890
  value: elOps.replace,
3650
- op: '$set',
3651
- kind: 'overlap',
3891
+ op: "$set",
3892
+ kind: "overlap",
3652
3893
  });
3653
3894
  }
3654
3895
  }
@@ -3658,19 +3899,21 @@ export class Mongo extends Db {
3658
3899
  }
3659
3900
  }
3660
3901
  };
3661
- detectOverlaps(fieldOps, '');
3902
+ detectOverlaps(fieldOps, "");
3662
3903
  if (warnings.length > 0) {
3663
- fjLog.warn('cry-db: bracket-by-_id warnings:', warnings);
3904
+ fjLog.warn("cry-db: bracket-by-_id warnings:", warnings);
3664
3905
  }
3665
3906
  if (update.$set && Object.keys(update.$set).length === 0)
3666
3907
  delete update.$set;
3667
- if (update.$unset && Object.keys(update.$unset).length === 0)
3908
+ if (update.$unset &&
3909
+ Object.keys(update.$unset).length === 0)
3668
3910
  delete update.$unset;
3669
3911
  const pipeline = [];
3670
3912
  if (update.$set && Object.keys(update.$set).length > 0) {
3671
3913
  pipeline.push({ $set: update.$set });
3672
3914
  }
3673
- if (update.$unset && Object.keys(update.$unset).length > 0) {
3915
+ if (update.$unset &&
3916
+ Object.keys(update.$unset).length > 0) {
3674
3917
  pipeline.push({ $unset: Object.keys(update.$unset) });
3675
3918
  }
3676
3919
  // Translate $inc / $currentDate so revisions (_rev/_ts) still update in pipeline form.
@@ -3686,7 +3929,9 @@ export class Mongo extends Db {
3686
3929
  },
3687
3930
  });
3688
3931
  }
3689
- return warnings.length > 0 ? { update: pipeline, warnings } : { update: pipeline };
3932
+ return warnings.length > 0
3933
+ ? { update: pipeline, warnings }
3934
+ : { update: pipeline };
3690
3935
  }
3691
3936
  async _processHashedKeys(obj) {
3692
3937
  const hashedKeys = Object.keys(obj).filter(startsWithHashedPrefix);
@@ -3742,10 +3987,10 @@ export class Mongo extends Db {
3742
3987
  }
3743
3988
  else {
3744
3989
  for (let key in ret) {
3745
- if (startsWithHashedPrefix(key)
3746
- || startsWithDoubleUnderscore(key)
3747
- || removeFields.has(key)
3748
- || this._removeFieldsAlways.has(key))
3990
+ if (startsWithHashedPrefix(key) ||
3991
+ startsWithDoubleUnderscore(key) ||
3992
+ removeFields.has(key) ||
3993
+ this._removeFieldsAlways.has(key))
3749
3994
  delete ret[key];
3750
3995
  }
3751
3996
  }