cry-db 2.1.26 → 2.1.29
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/base.d.ts +2 -1
- package/dist/base.d.ts.map +1 -0
- package/dist/base.js +35 -34
- package/dist/db.d.ts +2 -5
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +15 -29
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -36
- package/dist/mongo.d.ts +4 -5
- package/dist/mongo.d.ts.map +1 -0
- package/dist/mongo.js +259 -265
- package/dist/repo.d.ts +4 -3
- package/dist/repo.d.ts.map +1 -0
- package/dist/repo.js +11 -17
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -5
- package/package.json +2 -1
- package/dist/base.js.map +0 -1
- package/dist/db.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/mongo.js.map +0 -1
- package/dist/repo.js.map +0 -1
- package/dist/types.js.map +0 -1
package/dist/mongo.js
CHANGED
|
@@ -1,27 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const mongodb_1 = require("mongodb");
|
|
10
|
-
const tiny_typed_emitter_1 = require("tiny-typed-emitter");
|
|
11
|
-
const _1 = require(".");
|
|
12
|
-
const db_1 = require("./db");
|
|
13
|
-
const types_1 = require("./types");
|
|
14
|
-
const lodash_clonedeep_1 = __importDefault(require("lodash.clonedeep"));
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
import bcrypt from 'bcrypt';
|
|
3
|
+
import { ObjectId, ReadConcern, ReadPreference, Timestamp, WriteConcern } from 'mongodb';
|
|
4
|
+
import { TypedEmitter } from "tiny-typed-emitter";
|
|
5
|
+
import { Db, log } from './db.js';
|
|
6
|
+
import { SEQUENCES_COLLECTION } from './types.js';
|
|
7
|
+
import cloneDeep from "lodash.clonedeep";
|
|
8
|
+
import { Base } from "./base.js";
|
|
15
9
|
const saltRounds = 10;
|
|
16
10
|
const TRANSACTION_OPTIONS = {
|
|
17
11
|
defaultTransactionOptions: {
|
|
18
|
-
readPreference: new
|
|
19
|
-
readConcern: new
|
|
20
|
-
writeConcern: new
|
|
12
|
+
readPreference: new ReadPreference("primary"),
|
|
13
|
+
readConcern: new ReadConcern("local"),
|
|
14
|
+
writeConcern: new WriteConcern("majority")
|
|
21
15
|
}
|
|
22
16
|
};
|
|
23
|
-
|
|
24
|
-
class Mongo extends
|
|
17
|
+
export const DummyExportToFixTsCompilation = true;
|
|
18
|
+
export default class Mongo extends Db {
|
|
19
|
+
revisions;
|
|
20
|
+
softdelete;
|
|
21
|
+
session;
|
|
22
|
+
emittingPublishEvents;
|
|
23
|
+
auditing;
|
|
24
|
+
auditCollectionName;
|
|
25
|
+
auditedCollections;
|
|
26
|
+
emitter;
|
|
27
|
+
user;
|
|
28
|
+
audit;
|
|
29
|
+
syncSupport;
|
|
25
30
|
constructor(db, url) {
|
|
26
31
|
super(db, url);
|
|
27
32
|
this.revisions = false;
|
|
@@ -32,30 +37,21 @@ class Mongo extends db_1.Db {
|
|
|
32
37
|
this.auditing = false;
|
|
33
38
|
this.auditCollectionName = "dblog";
|
|
34
39
|
this.auditedCollections = this.auditCollections(process.env.AUDIT_COLLECTIONS || []);
|
|
35
|
-
this.emitter = new
|
|
40
|
+
this.emitter = new TypedEmitter();
|
|
36
41
|
this.user = undefined;
|
|
37
42
|
this.audit = undefined;
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
static newid() {
|
|
41
|
-
return db_1.Db.newid();
|
|
42
|
-
}
|
|
43
|
-
static toId(id) {
|
|
44
|
-
return db_1.Db.toId(id);
|
|
45
|
-
}
|
|
46
|
-
static objectid(o) {
|
|
47
|
-
return db_1.Db.objectid(o);
|
|
43
|
+
log.debug('new Mongo:', this.url, this.db);
|
|
48
44
|
}
|
|
49
45
|
on(evt, listener) {
|
|
50
|
-
|
|
46
|
+
log.debug("on", evt, listener);
|
|
51
47
|
this.emitter.on(evt, listener);
|
|
52
48
|
}
|
|
53
49
|
off(evt, listener) {
|
|
54
|
-
|
|
50
|
+
log.debug("off", evt, listener);
|
|
55
51
|
this.emitter.off(evt, listener);
|
|
56
52
|
}
|
|
57
53
|
once(evt, listener) {
|
|
58
|
-
|
|
54
|
+
log.debug("off", evt, listener);
|
|
59
55
|
this.emitter.off(evt, listener);
|
|
60
56
|
}
|
|
61
57
|
setUser(username) {
|
|
@@ -125,29 +121,29 @@ class Mongo extends db_1.Db {
|
|
|
125
121
|
return this.emittingPublishEvents;
|
|
126
122
|
}
|
|
127
123
|
async distinct(collection, field) {
|
|
128
|
-
|
|
124
|
+
log.debug('distinct called', collection, field);
|
|
129
125
|
let ret = await this.executeTransactionally(collection, async (conn) => {
|
|
130
126
|
return await conn.distinct(field);
|
|
131
127
|
}, false, { operation: "distinct", collection, field });
|
|
132
|
-
|
|
128
|
+
log.debug('distinct returns', ret);
|
|
133
129
|
return ret;
|
|
134
130
|
}
|
|
135
131
|
async count(collection, query = {}, opts = {}) {
|
|
136
|
-
|
|
132
|
+
log.debug('distinct called', collection, query, opts);
|
|
137
133
|
let ret = await this.executeTransactionally(collection, async (conn) => {
|
|
138
134
|
return await conn.countDocuments(query, opts);
|
|
139
135
|
}, false, { operation: "count", collection, query, opts });
|
|
140
|
-
|
|
136
|
+
log.debug('count returns', ret);
|
|
141
137
|
return ret;
|
|
142
138
|
}
|
|
143
139
|
async find(collection, query = {}, opts = {}) {
|
|
144
|
-
(
|
|
140
|
+
assert(collection);
|
|
145
141
|
query = this.replaceIds(query);
|
|
146
142
|
if (this.softdelete) {
|
|
147
143
|
if (!query._deleted)
|
|
148
144
|
query._deleted = { $exists: false };
|
|
149
145
|
}
|
|
150
|
-
|
|
146
|
+
log.debug('find called', collection, query, opts);
|
|
151
147
|
let ret = await this.executeTransactionally(collection, async (conn) => {
|
|
152
148
|
let optsIn = {};
|
|
153
149
|
if (opts.readPreference)
|
|
@@ -168,11 +164,11 @@ class Mongo extends db_1.Db {
|
|
|
168
164
|
let res = await r.toArray();
|
|
169
165
|
return this._processReturnedObject(res);
|
|
170
166
|
}, false, { operation: "find", collection, query, opts });
|
|
171
|
-
|
|
167
|
+
log.debug('find returns', ret);
|
|
172
168
|
return ret;
|
|
173
169
|
}
|
|
174
170
|
async findAll(collection, query = {}, opts = {}) {
|
|
175
|
-
(
|
|
171
|
+
assert(collection);
|
|
176
172
|
query = this.replaceIds(query);
|
|
177
173
|
let ret = await this.executeTransactionally(collection, async (conn) => {
|
|
178
174
|
let optsIn = {};
|
|
@@ -193,12 +189,12 @@ class Mongo extends db_1.Db {
|
|
|
193
189
|
r = r.collation(opts.collation);
|
|
194
190
|
return this._processReturnedObject(await r.toArray());
|
|
195
191
|
}, false, { operation: "findAll", collection, query, opts });
|
|
196
|
-
|
|
192
|
+
log.debug('findAll returns', ret);
|
|
197
193
|
return ret;
|
|
198
194
|
}
|
|
199
195
|
async findNewer(collection, timestamp, query = {}, opts = {}) {
|
|
200
196
|
query = this._createQueryForNewer(timestamp, query);
|
|
201
|
-
|
|
197
|
+
log.debug('findNewer called', collection, timestamp, query, opts);
|
|
202
198
|
let ret = await this.executeTransactionally(collection, async (conn) => {
|
|
203
199
|
let optsIn = {};
|
|
204
200
|
if (opts.readPreference)
|
|
@@ -220,11 +216,11 @@ class Mongo extends db_1.Db {
|
|
|
220
216
|
r = r.collation(opts.collation);
|
|
221
217
|
return this._processReturnedObject(await r.toArray());
|
|
222
218
|
}, false, { operation: "findNewer", collection, timestamp, query, opts });
|
|
223
|
-
|
|
219
|
+
log.debug('findNewer returns', ret);
|
|
224
220
|
return ret;
|
|
225
221
|
}
|
|
226
222
|
async findNewerMany(spec = []) {
|
|
227
|
-
|
|
223
|
+
log.debug('findNewerMany called', spec);
|
|
228
224
|
let conn = await this.connect();
|
|
229
225
|
const getOneColl = async (coll) => {
|
|
230
226
|
let query = this._createQueryForNewer(coll.timestamp, coll.query);
|
|
@@ -257,7 +253,7 @@ class Mongo extends db_1.Db {
|
|
|
257
253
|
_createQueryForNewer(timestamp, query) {
|
|
258
254
|
let ts = (timestamp === 1 || timestamp === "1" || timestamp === "0" || timestamp === 0)
|
|
259
255
|
? {}
|
|
260
|
-
: { _ts: { $gt:
|
|
256
|
+
: { _ts: { $gt: Base.timestamp(timestamp) } };
|
|
261
257
|
query = {
|
|
262
258
|
...ts,
|
|
263
259
|
...(query || {}),
|
|
@@ -267,7 +263,7 @@ class Mongo extends db_1.Db {
|
|
|
267
263
|
}
|
|
268
264
|
async findAfter(collection, csq, query = {}, opts = {}) {
|
|
269
265
|
query._csq = { $gt: csq };
|
|
270
|
-
|
|
266
|
+
log.debug('findAfter called', collection, csq, query, opts);
|
|
271
267
|
let ret = await this.executeTransactionally(collection, async (conn) => {
|
|
272
268
|
let optsIn = {};
|
|
273
269
|
if (opts.readPreference)
|
|
@@ -289,11 +285,11 @@ class Mongo extends db_1.Db {
|
|
|
289
285
|
r = r.collation(opts.collation);
|
|
290
286
|
return this._processReturnedObject(await r.toArray());
|
|
291
287
|
}, false, { operation: "findNewer", collection, csq, query, opts });
|
|
292
|
-
|
|
288
|
+
log.debug('findNewer returns', ret);
|
|
293
289
|
return ret;
|
|
294
290
|
}
|
|
295
291
|
async findAfterMany(spec = []) {
|
|
296
|
-
|
|
292
|
+
log.debug('findAfterMany called', spec);
|
|
297
293
|
let conn = await this.connect();
|
|
298
294
|
const getOneColl = async (coll) => {
|
|
299
295
|
let r = conn
|
|
@@ -325,57 +321,57 @@ class Mongo extends db_1.Db {
|
|
|
325
321
|
return out;
|
|
326
322
|
}
|
|
327
323
|
async findNewerFromDate(collection, date, query = {}, opts = {}) {
|
|
328
|
-
let ts = new
|
|
329
|
-
|
|
324
|
+
let ts = new Timestamp(0, new Date(date).valueOf() / 1000);
|
|
325
|
+
log.debug('findNewerFromDate called', collection, date, query, opts);
|
|
330
326
|
let ret = await Mongo.prototype.findNewer.call(this, collection, ts, query, opts); // prevent calling Repo.findNewer
|
|
331
|
-
|
|
327
|
+
log.debug('findNewerFromDate returns', ret);
|
|
332
328
|
return ret;
|
|
333
329
|
}
|
|
334
330
|
async findOne(collection, query, projection) {
|
|
335
|
-
(
|
|
336
|
-
(
|
|
331
|
+
assert(collection);
|
|
332
|
+
assert(query);
|
|
337
333
|
query = this.replaceIds(query);
|
|
338
334
|
if (!query._deleted)
|
|
339
335
|
query._deleted = { $exists: false };
|
|
340
336
|
// if (!query._blocked) query._blocked = { $exists: false }; // intentionally - blocked records are returned
|
|
341
|
-
|
|
342
|
-
let ret = await this.executeTransactionally(collection, async (conn) => await conn.findOne(query, { projection
|
|
343
|
-
|
|
337
|
+
log.debug('findOne called', collection, query, projection);
|
|
338
|
+
let ret = await this.executeTransactionally(collection, async (conn) => await conn.findOne(query, { ...(projection ? { projection } : {}), ...this._sessionOpt() }), false, { operation: "findOne", collection, query, projection });
|
|
339
|
+
log.debug('findOne returns', ret);
|
|
344
340
|
return this._processReturnedObject(ret);
|
|
345
341
|
}
|
|
346
342
|
async findById(collection, id, projection) {
|
|
347
|
-
(
|
|
348
|
-
(
|
|
343
|
+
assert(collection);
|
|
344
|
+
assert(id);
|
|
349
345
|
if (!id)
|
|
350
346
|
return null;
|
|
351
347
|
let query = {
|
|
352
348
|
_id: Mongo._toId(id),
|
|
353
349
|
// _deleted: { $exists: false }
|
|
354
350
|
};
|
|
355
|
-
|
|
356
|
-
|
|
351
|
+
log.debug('findById called', this.db, collection, id, projection);
|
|
352
|
+
log.trace('findById executing with query', collection, query, projection);
|
|
357
353
|
let ret = await this.executeTransactionally(collection, async (conn) => {
|
|
358
|
-
let r = await conn.findOne(query, { projection
|
|
354
|
+
let r = await conn.findOne(query, { ...(projection ? { projection } : {}), ...this._sessionOpt() });
|
|
359
355
|
return r;
|
|
360
356
|
}, false, { operation: "findById", collection, id, projection });
|
|
361
|
-
if (ret
|
|
357
|
+
if (ret?._deleted)
|
|
362
358
|
ret = null;
|
|
363
|
-
|
|
359
|
+
log.debug('findById returns', ret);
|
|
364
360
|
return this._processReturnedObject(ret);
|
|
365
361
|
}
|
|
366
362
|
async updateOne(collection, query, update, options = { returnFullObject: false }) {
|
|
367
|
-
(
|
|
368
|
-
(
|
|
369
|
-
(
|
|
363
|
+
assert(collection);
|
|
364
|
+
assert(query);
|
|
365
|
+
assert(update);
|
|
370
366
|
query = this.replaceIds(query);
|
|
371
367
|
update = this.replaceIds(update);
|
|
372
368
|
let opts = {
|
|
373
369
|
upsert: false,
|
|
374
370
|
returnDocument: "after",
|
|
375
|
-
|
|
371
|
+
...this._sessionOpt()
|
|
376
372
|
};
|
|
377
373
|
update = await this._processUpdateObject(update);
|
|
378
|
-
|
|
374
|
+
log.debug('updateOne called', collection, query, update);
|
|
379
375
|
let seqKeys = this._findSequenceKeys(update.$set);
|
|
380
376
|
let obj = await this.executeTransactionally(collection, async (conn, client) => {
|
|
381
377
|
update.$set = update.$set || {};
|
|
@@ -386,25 +382,25 @@ class Mongo extends db_1.Db {
|
|
|
386
382
|
let res = await conn.findOneAndUpdate(query, update, opts);
|
|
387
383
|
if (!res.value)
|
|
388
384
|
return null;
|
|
389
|
-
let resObj = this._removeUnchanged(res.value, update, !!
|
|
385
|
+
let resObj = this._removeUnchanged(res.value, update, !!options?.returnFullObject);
|
|
390
386
|
await this._publishAndAudit('update', this.db, collection, resObj);
|
|
391
387
|
return resObj;
|
|
392
388
|
}, !!seqKeys, { operation: "updateOne", collection, query, update, options });
|
|
393
|
-
|
|
389
|
+
log.debug('updateOne returns', obj);
|
|
394
390
|
return this._processReturnedObject(await obj);
|
|
395
391
|
}
|
|
396
392
|
async save(collection, update, id = undefined, options = { returnFullObject: false }) {
|
|
397
|
-
(
|
|
398
|
-
(
|
|
393
|
+
assert(collection);
|
|
394
|
+
assert(update);
|
|
399
395
|
update = this.replaceIds(update);
|
|
400
396
|
let opts = {
|
|
401
397
|
upsert: true,
|
|
402
398
|
returnDocument: "after",
|
|
403
|
-
|
|
399
|
+
...this._sessionOpt()
|
|
404
400
|
};
|
|
405
401
|
let _id = Mongo.toId(id || update._id) || Mongo.newid();
|
|
406
402
|
update = await this._processUpdateObject(update);
|
|
407
|
-
|
|
403
|
+
log.debug('save called', collection, id, update);
|
|
408
404
|
let seqKeys = this._findSequenceKeys(update.$set);
|
|
409
405
|
let obj = await this.executeTransactionally(collection, async (conn, client) => {
|
|
410
406
|
update.$set = update.$set || {};
|
|
@@ -415,19 +411,19 @@ class Mongo extends db_1.Db {
|
|
|
415
411
|
let res = await conn.findOneAndUpdate({ _id }, update, opts);
|
|
416
412
|
if (!res.value)
|
|
417
413
|
return null;
|
|
418
|
-
let resObj = this._removeUnchanged(res.value, update, !!
|
|
414
|
+
let resObj = this._removeUnchanged(res.value, update, !!options?.returnFullObject);
|
|
419
415
|
await this._publishAndAudit('update', this.db, collection, resObj);
|
|
420
416
|
return resObj;
|
|
421
417
|
}, !!seqKeys, { operation: "save", collection, _id, update, options });
|
|
422
|
-
|
|
418
|
+
log.debug('save returns', obj);
|
|
423
419
|
return this._processReturnedObject(await obj);
|
|
424
420
|
}
|
|
425
421
|
async update(collection, query, update) {
|
|
426
|
-
(
|
|
427
|
-
(
|
|
428
|
-
(
|
|
422
|
+
assert(collection);
|
|
423
|
+
assert(query);
|
|
424
|
+
assert(update);
|
|
429
425
|
if (this.syncSupport)
|
|
430
|
-
|
|
426
|
+
log.warn("update does not increase _csq, avoit it.");
|
|
431
427
|
if (!Object.keys(update).length)
|
|
432
428
|
return { n: 0, ok: false };
|
|
433
429
|
query = this.replaceIds(query);
|
|
@@ -435,10 +431,10 @@ class Mongo extends db_1.Db {
|
|
|
435
431
|
let opts = {
|
|
436
432
|
upsert: false,
|
|
437
433
|
returnDocument: "after",
|
|
438
|
-
|
|
434
|
+
...this._sessionOpt()
|
|
439
435
|
};
|
|
440
436
|
update = await this._processUpdateObject(update);
|
|
441
|
-
|
|
437
|
+
log.debug('update called', collection, query, update);
|
|
442
438
|
let seqKeys = this._findSequenceKeys(update.$set);
|
|
443
439
|
let obj = await this.executeTransactionally(collection, async (conn, client) => {
|
|
444
440
|
update.$set = update.$set || {};
|
|
@@ -446,7 +442,7 @@ class Mongo extends db_1.Db {
|
|
|
446
442
|
await this._processSequenceField(client, collection, update.$set, seqKeys);
|
|
447
443
|
if (update.$set === undefined || Object.keys(update.$set).length === 0)
|
|
448
444
|
delete update.$set;
|
|
449
|
-
|
|
445
|
+
log.debug('update called', collection, query, update);
|
|
450
446
|
let res = await conn.updateMany(query, update, opts);
|
|
451
447
|
let resObj = {
|
|
452
448
|
n: res.modifiedCount,
|
|
@@ -455,14 +451,14 @@ class Mongo extends db_1.Db {
|
|
|
455
451
|
await this._publishAndAudit('updateMany', this.db, collection, resObj);
|
|
456
452
|
return resObj;
|
|
457
453
|
}, !!seqKeys, { operation: "update", collection, query, update });
|
|
458
|
-
|
|
454
|
+
log.debug('update returns', obj);
|
|
459
455
|
return await obj;
|
|
460
456
|
}
|
|
461
457
|
async upsert(collection, query, update, options = { returnFullObject: false }) {
|
|
462
|
-
(
|
|
463
|
-
(
|
|
464
|
-
(
|
|
465
|
-
(
|
|
458
|
+
assert(collection);
|
|
459
|
+
assert(query);
|
|
460
|
+
assert(update);
|
|
461
|
+
assert(typeof update === 'object', 'update must be an object');
|
|
466
462
|
// if (!Object.keys(update).length) return null;
|
|
467
463
|
query = this.replaceIds(query);
|
|
468
464
|
update = this.replaceIds(update);
|
|
@@ -470,16 +466,15 @@ class Mongo extends db_1.Db {
|
|
|
470
466
|
...options,
|
|
471
467
|
upsert: true,
|
|
472
468
|
returnDocument: "after",
|
|
473
|
-
|
|
469
|
+
...this._sessionOpt()
|
|
474
470
|
};
|
|
475
|
-
|
|
471
|
+
log.debug('upsert called', collection, query, update);
|
|
476
472
|
update = await this._processUpdateObject(update);
|
|
477
473
|
let seqKeys = this._findSequenceKeys(update.$set);
|
|
478
|
-
|
|
474
|
+
log.debug('upsert processed', collection, query, update);
|
|
479
475
|
if (Object.keys(query).length === 0)
|
|
480
476
|
query._id = Mongo.newid();
|
|
481
477
|
let ret = await this.executeTransactionally(collection, async (conn, client) => {
|
|
482
|
-
var _a;
|
|
483
478
|
update.$set = update.$set || {};
|
|
484
479
|
if (seqKeys)
|
|
485
480
|
await this._processSequenceField(client, collection, update.$set, seqKeys);
|
|
@@ -487,50 +482,49 @@ class Mongo extends db_1.Db {
|
|
|
487
482
|
delete update.$set;
|
|
488
483
|
let ret = await conn.findOneAndUpdate(query, update, opts);
|
|
489
484
|
if (ret.value) {
|
|
490
|
-
let oper =
|
|
491
|
-
let retObj = oper === "insert" ? ret.value : this._removeUnchanged(ret.value, update, !!
|
|
485
|
+
let oper = ret.lastErrorObject?.updatedExisting ? "update" : "insert";
|
|
486
|
+
let retObj = oper === "insert" ? ret.value : this._removeUnchanged(ret.value, update, !!options?.returnFullObject);
|
|
492
487
|
await this._publishAndAudit(oper, this.db, collection, retObj);
|
|
493
488
|
return retObj;
|
|
494
489
|
}
|
|
495
490
|
;
|
|
496
491
|
return ret;
|
|
497
492
|
}, !!seqKeys, { operation: "upsert", query, update, options });
|
|
498
|
-
|
|
493
|
+
log.debug('upsert returns', ret);
|
|
499
494
|
return this._processReturnedObject(await ret);
|
|
500
495
|
}
|
|
501
496
|
async insert(collection, insert) {
|
|
502
|
-
(
|
|
503
|
-
(
|
|
504
|
-
(
|
|
505
|
-
|
|
497
|
+
assert(collection, "collection can't be null");
|
|
498
|
+
assert(insert, "insert can't be null");
|
|
499
|
+
assert(typeof insert === "object", "insert must be an object");
|
|
500
|
+
log.debug('insert called', collection, insert);
|
|
506
501
|
insert = this.replaceIds(insert);
|
|
507
502
|
if (this.revisions) {
|
|
508
503
|
insert._rev = 1;
|
|
509
|
-
insert._ts =
|
|
504
|
+
insert._ts = Base.timestamp();
|
|
510
505
|
}
|
|
511
506
|
await this._processHashedKeys(insert);
|
|
512
507
|
let seqKeys = this._findSequenceKeys(insert);
|
|
513
508
|
let ret = await this.executeTransactionally(collection, async (conn, client) => {
|
|
514
509
|
if (insert)
|
|
515
510
|
insert = await this._processSequenceField(client, collection, insert, seqKeys);
|
|
516
|
-
let obj = await conn.insertOne(insert,
|
|
511
|
+
let obj = await conn.insertOne(insert, this._sessionOpt());
|
|
517
512
|
let fullObj = { _id: obj.insertedId, ...insert };
|
|
518
513
|
await this._publishAndAudit('insert', this.db, collection, fullObj);
|
|
519
514
|
return fullObj;
|
|
520
515
|
}, !!seqKeys, { operation: "insert", collection, insert });
|
|
521
|
-
|
|
516
|
+
log.debug('insert returns', ret);
|
|
522
517
|
return this._processReturnedObject(await ret);
|
|
523
518
|
}
|
|
524
519
|
async upsertBatch(collection, batch) {
|
|
525
|
-
(
|
|
526
|
-
(
|
|
527
|
-
(
|
|
528
|
-
|
|
520
|
+
assert(collection, "collection can't be null");
|
|
521
|
+
assert(batch, "batch can't be null");
|
|
522
|
+
assert(batch instanceof Array, "batch must be an Array");
|
|
523
|
+
log.debug('upsertBatch called', collection, batch);
|
|
529
524
|
batch = this.replaceIds(batch);
|
|
530
525
|
for (let i = 0; i < batch.length; i++)
|
|
531
|
-
await this._processHashedKeys(batch[i]
|
|
526
|
+
await this._processHashedKeys(batch[i]?.update);
|
|
532
527
|
let ret = await this.executeTransactionally(collection, async (conn, client) => {
|
|
533
|
-
var _a, _b;
|
|
534
528
|
await this._processSequenceFieldForMany(client, collection, batch.map(b => b.update));
|
|
535
529
|
let publications = [];
|
|
536
530
|
let changes = [];
|
|
@@ -540,13 +534,13 @@ class Mongo extends db_1.Db {
|
|
|
540
534
|
...(opts || {}),
|
|
541
535
|
upsert: true,
|
|
542
536
|
returnDocument: "after",
|
|
543
|
-
|
|
537
|
+
...this._sessionOpt()
|
|
544
538
|
};
|
|
545
539
|
update = await this._processUpdateObject(update);
|
|
546
540
|
let ret = (await conn.findOneAndUpdate(query, update, options));
|
|
547
|
-
if (
|
|
548
|
-
let oper =
|
|
549
|
-
let retObj = oper === "insert" ? ret.value : this._removeUnchanged(ret.value, update, !!
|
|
541
|
+
if (ret?.value?._id) {
|
|
542
|
+
let oper = ret.lastErrorObject?.updatedExisting ? "update" : "insert";
|
|
543
|
+
let retObj = oper === "insert" ? ret.value : this._removeUnchanged(ret.value, update, !!opts?.returnFullObject);
|
|
550
544
|
publications.push(await this._publishAndAudit(oper, this.db, collection, retObj, true));
|
|
551
545
|
changes.push(retObj);
|
|
552
546
|
}
|
|
@@ -559,28 +553,28 @@ class Mongo extends db_1.Db {
|
|
|
559
553
|
operation: "batch",
|
|
560
554
|
db: this.db,
|
|
561
555
|
collection,
|
|
562
|
-
data: publications.map(p => p
|
|
556
|
+
data: publications.map(p => p?.payload).filter(p => !!p)
|
|
563
557
|
}
|
|
564
558
|
});
|
|
565
559
|
}
|
|
566
560
|
return changes;
|
|
567
561
|
}, false, { operation: "upsertBatch", collection, batch });
|
|
568
|
-
|
|
562
|
+
log.debug('upsertBatch returns', ret);
|
|
569
563
|
return ret;
|
|
570
564
|
}
|
|
571
565
|
async insertMany(collection, insert) {
|
|
572
|
-
(
|
|
573
|
-
(
|
|
574
|
-
(
|
|
575
|
-
|
|
566
|
+
assert(collection, "collection can't be null");
|
|
567
|
+
assert(insert, "insert can't be null");
|
|
568
|
+
assert(insert instanceof Array, "insert must be an Array");
|
|
569
|
+
log.debug('insertMany called', collection, insert);
|
|
576
570
|
insert = this.replaceIds(insert);
|
|
577
571
|
for (let i = 0; i < insert.length; i++)
|
|
578
572
|
await this._processHashedKeys(insert[i]);
|
|
579
573
|
if (this.revisions)
|
|
580
|
-
insert.forEach(ins => { ins._rev = 1; ins._ts =
|
|
574
|
+
insert.forEach(ins => { ins._rev = 1; ins._ts = Base.timestamp(); });
|
|
581
575
|
let ret = await this.executeTransactionally(collection, async (conn, client) => {
|
|
582
576
|
await this._processSequenceFieldForMany(client, collection, insert);
|
|
583
|
-
let obj = await conn.insertMany(insert,
|
|
577
|
+
let obj = await conn.insertMany(insert, this._sessionOpt());
|
|
584
578
|
let ret = [];
|
|
585
579
|
for (let ns of Object.keys(obj.insertedIds)) {
|
|
586
580
|
let n = Number(ns);
|
|
@@ -597,35 +591,35 @@ class Mongo extends db_1.Db {
|
|
|
597
591
|
}
|
|
598
592
|
return ret;
|
|
599
593
|
}, false, { operation: "insertMany", collection, insert });
|
|
600
|
-
|
|
594
|
+
log.debug('insertMany returns', ret);
|
|
601
595
|
return ret;
|
|
602
596
|
}
|
|
603
597
|
async deleteOne(collection, query) {
|
|
604
|
-
(
|
|
605
|
-
(
|
|
598
|
+
assert(collection);
|
|
599
|
+
assert(query);
|
|
606
600
|
query = this.replaceIds(query);
|
|
607
601
|
if (!this.softdelete) {
|
|
608
602
|
let opts = {
|
|
609
603
|
returnDocument: "after",
|
|
610
|
-
|
|
604
|
+
...this._sessionOpt()
|
|
611
605
|
};
|
|
612
|
-
|
|
606
|
+
log.debug('deleteOne called', collection, query);
|
|
613
607
|
let ret = await this.executeTransactionally(collection, async (conn) => {
|
|
614
608
|
let obj = await conn.findOneAndDelete(query, opts);
|
|
615
609
|
if (obj.value)
|
|
616
610
|
await this._publishAndAudit('delete', this.db, collection, obj.value);
|
|
617
611
|
return obj.value;
|
|
618
612
|
}, false, { operation: "deleteOne", collection, query, softdelete: this.softdelete });
|
|
619
|
-
|
|
613
|
+
log.debug('deleteOne returns', ret);
|
|
620
614
|
return ret;
|
|
621
615
|
}
|
|
622
616
|
else {
|
|
623
617
|
let opts = {
|
|
624
618
|
upsert: true,
|
|
625
619
|
returnDocument: "after",
|
|
626
|
-
|
|
620
|
+
...this._sessionOpt()
|
|
627
621
|
};
|
|
628
|
-
|
|
622
|
+
log.debug('deleteOne called', collection, query);
|
|
629
623
|
let ret = await this.executeTransactionally(collection, async (conn, client) => {
|
|
630
624
|
let del = {
|
|
631
625
|
$set: { _deleted: new Date() },
|
|
@@ -639,7 +633,7 @@ class Mongo extends db_1.Db {
|
|
|
639
633
|
await this._publishAndAudit('delete', this.db, collection, obj.value);
|
|
640
634
|
return obj.value;
|
|
641
635
|
}, false, { operation: "deleteOne", collection, query, softdelete: this.softdelete });
|
|
642
|
-
|
|
636
|
+
log.debug('deleteOne returns', ret);
|
|
643
637
|
return ret;
|
|
644
638
|
}
|
|
645
639
|
}
|
|
@@ -647,10 +641,10 @@ class Mongo extends db_1.Db {
|
|
|
647
641
|
let opts = {
|
|
648
642
|
upsert: false,
|
|
649
643
|
returnDocument: "after",
|
|
650
|
-
|
|
644
|
+
...this._sessionOpt()
|
|
651
645
|
};
|
|
652
646
|
query = this.replaceIds(query);
|
|
653
|
-
|
|
647
|
+
log.debug('blockOne called', collection, query);
|
|
654
648
|
let ret = await this.executeTransactionally(collection, async (conn, client) => {
|
|
655
649
|
query._blocked = { $exists: 0 };
|
|
656
650
|
let update = {
|
|
@@ -672,17 +666,17 @@ class Mongo extends db_1.Db {
|
|
|
672
666
|
await this._publishAndAudit('block', this.db, collection, retObj);
|
|
673
667
|
return retObj;
|
|
674
668
|
}, false, { operation: "blockOne", collection, query });
|
|
675
|
-
|
|
669
|
+
log.debug('blockOne returns', ret);
|
|
676
670
|
return ret;
|
|
677
671
|
}
|
|
678
672
|
async unblockOne(collection, query) {
|
|
679
673
|
let opts = {
|
|
680
674
|
upsert: false,
|
|
681
675
|
returnDocument: "after",
|
|
682
|
-
|
|
676
|
+
...this._sessionOpt()
|
|
683
677
|
};
|
|
684
678
|
query = this.replaceIds(query);
|
|
685
|
-
|
|
679
|
+
log.debug('unblockOne called', collection, query);
|
|
686
680
|
let ret = await this.executeTransactionally(collection, async (conn, client) => {
|
|
687
681
|
query._blocked = { $exists: 1 };
|
|
688
682
|
let update = {
|
|
@@ -703,18 +697,18 @@ class Mongo extends db_1.Db {
|
|
|
703
697
|
await this._publishAndAudit('unblock', this.db, collection, retObj);
|
|
704
698
|
return retObj;
|
|
705
699
|
}, false, { operation: "unblockOne", collection, query });
|
|
706
|
-
|
|
700
|
+
log.debug('unblockOne returns', ret);
|
|
707
701
|
return ret;
|
|
708
702
|
}
|
|
709
703
|
async hardDeleteOne(collection, query) {
|
|
710
|
-
(
|
|
711
|
-
(
|
|
704
|
+
assert(collection);
|
|
705
|
+
assert(query);
|
|
712
706
|
query = this.replaceIds(query);
|
|
713
707
|
let opts = {
|
|
714
708
|
returnDocument: "after",
|
|
715
|
-
|
|
709
|
+
...this._sessionOpt()
|
|
716
710
|
};
|
|
717
|
-
|
|
711
|
+
log.debug('hardDeleteOne called', collection, query);
|
|
718
712
|
let ret = await this.executeTransactionally(collection, async (conn) => {
|
|
719
713
|
let obj = await conn.findOneAndDelete(query, opts);
|
|
720
714
|
if (obj.value) {
|
|
@@ -722,21 +716,21 @@ class Mongo extends db_1.Db {
|
|
|
722
716
|
}
|
|
723
717
|
return obj.value;
|
|
724
718
|
}, false, { operation: "hardDeleteOne", collection, query });
|
|
725
|
-
|
|
719
|
+
log.debug('hardDeleteOne returns', ret);
|
|
726
720
|
return ret;
|
|
727
721
|
}
|
|
728
722
|
async delete(collection, query) {
|
|
729
|
-
(
|
|
730
|
-
(
|
|
723
|
+
assert(collection);
|
|
724
|
+
assert(query);
|
|
731
725
|
if (this.syncSupport)
|
|
732
|
-
|
|
726
|
+
log.warn("delete does not increase _csq, avoit it.");
|
|
733
727
|
query = this.replaceIds(query);
|
|
734
728
|
if (!this.softdelete) {
|
|
735
729
|
let opts = {
|
|
736
730
|
returnDocument: "after",
|
|
737
|
-
|
|
731
|
+
...this._sessionOpt()
|
|
738
732
|
};
|
|
739
|
-
|
|
733
|
+
log.debug('delete called', collection, query);
|
|
740
734
|
let ret = await this.executeTransactionally(collection, async (conn) => {
|
|
741
735
|
let obj = await conn.deleteMany(query, opts);
|
|
742
736
|
let resObj = {
|
|
@@ -746,17 +740,17 @@ class Mongo extends db_1.Db {
|
|
|
746
740
|
await this._publishAndAudit('deleteMany', this.db, collection, resObj);
|
|
747
741
|
return resObj;
|
|
748
742
|
}, false, { operation: "delete", collection, query, softdelete: this.softdelete });
|
|
749
|
-
|
|
743
|
+
log.debug('delete returns', ret);
|
|
750
744
|
return ret;
|
|
751
745
|
}
|
|
752
746
|
else {
|
|
753
747
|
let opts = {
|
|
754
748
|
upsert: false,
|
|
755
749
|
returnDocument: "after",
|
|
756
|
-
|
|
750
|
+
...this._sessionOpt()
|
|
757
751
|
};
|
|
758
752
|
let date = new Date();
|
|
759
|
-
|
|
753
|
+
log.debug('delete called', collection, query);
|
|
760
754
|
let ret = await this.executeTransactionally(collection, async (conn) => {
|
|
761
755
|
let obj = await conn.updateMany(query, { $set: { _deleted: date } }, opts);
|
|
762
756
|
let resObj = {
|
|
@@ -766,21 +760,21 @@ class Mongo extends db_1.Db {
|
|
|
766
760
|
await this._publishAndAudit('deleteMany', this.db, collection, resObj);
|
|
767
761
|
return resObj;
|
|
768
762
|
}, false, { operation: "delete", collection, query, softdelete: this.softdelete });
|
|
769
|
-
|
|
763
|
+
log.debug('delete returns', ret);
|
|
770
764
|
return ret;
|
|
771
765
|
}
|
|
772
766
|
}
|
|
773
767
|
async hardDelete(collection, query) {
|
|
774
|
-
(
|
|
775
|
-
(
|
|
768
|
+
assert(collection);
|
|
769
|
+
assert(query);
|
|
776
770
|
if (this.syncSupport)
|
|
777
|
-
|
|
771
|
+
log.warn("hardDelete does not increase _csq, avoit it.");
|
|
778
772
|
query = this.replaceIds(query);
|
|
779
773
|
let opts = {
|
|
780
774
|
returnDocument: "after",
|
|
781
|
-
|
|
775
|
+
...this._sessionOpt()
|
|
782
776
|
};
|
|
783
|
-
|
|
777
|
+
log.debug('hardDelete called', collection, query);
|
|
784
778
|
let ret = await this.executeTransactionally(collection, async (conn) => {
|
|
785
779
|
let obj = await conn.deleteMany(query, opts);
|
|
786
780
|
let resObj = {
|
|
@@ -790,12 +784,12 @@ class Mongo extends db_1.Db {
|
|
|
790
784
|
await this._publishAndAudit('deleteMany', this.db, collection, resObj);
|
|
791
785
|
return resObj;
|
|
792
786
|
}, false, { operation: "hardDelete", collection, query, softdelete: this.softdelete });
|
|
793
|
-
|
|
787
|
+
log.debug('hardDelete returns', ret);
|
|
794
788
|
return ret;
|
|
795
789
|
}
|
|
796
790
|
async testHash(collection, query, field, unhashedValue) {
|
|
797
791
|
let _field;
|
|
798
|
-
|
|
792
|
+
log.debug('teshHash called', collection, query, field, unhashedValue);
|
|
799
793
|
if (typeof field === "object") {
|
|
800
794
|
if (Object.keys(field).length === 1)
|
|
801
795
|
[_field, unhashedValue] = Object.entries(field)[0];
|
|
@@ -807,21 +801,21 @@ class Mongo extends db_1.Db {
|
|
|
807
801
|
if (!/^__hashed__/.test(_field))
|
|
808
802
|
_field = "__hashed__" + _field;
|
|
809
803
|
let conn = await this.connect();
|
|
810
|
-
let obj = await conn.db(this.db).collection(collection).findOne(query, { projection: { [_field]: 1 },
|
|
804
|
+
let obj = await conn.db(this.db).collection(collection).findOne(query, { projection: { [_field]: 1 }, ...this._sessionOpt() });
|
|
811
805
|
if (!obj || !obj[_field]) {
|
|
812
|
-
|
|
806
|
+
log.debug('teshHash returns false', obj);
|
|
813
807
|
return false;
|
|
814
808
|
}
|
|
815
|
-
let res = await
|
|
816
|
-
|
|
809
|
+
let res = await bcrypt.compare(unhashedValue, obj[_field].hash);
|
|
810
|
+
log.debug('teshHash returns', res);
|
|
817
811
|
return res;
|
|
818
812
|
}
|
|
819
813
|
async aggregate(collection, pipeline, opts = {
|
|
820
|
-
readPreference:
|
|
814
|
+
readPreference: ReadPreference.SECONDARY_PREFERRED,
|
|
821
815
|
}) {
|
|
822
|
-
(
|
|
823
|
-
(
|
|
824
|
-
|
|
816
|
+
assert(collection);
|
|
817
|
+
assert(pipeline instanceof Array);
|
|
818
|
+
log.debug('aggregate called', collection, pipeline);
|
|
825
819
|
pipeline = this.replaceIds(pipeline);
|
|
826
820
|
if (this.session)
|
|
827
821
|
opts.session = this.session;
|
|
@@ -829,15 +823,15 @@ class Mongo extends db_1.Db {
|
|
|
829
823
|
let res = await conn.aggregate(pipeline, opts).toArray();
|
|
830
824
|
return res;
|
|
831
825
|
}, false, { operation: "aggregate", collection, pipeline, opts });
|
|
832
|
-
|
|
826
|
+
log.debug('aggregare returns', ret);
|
|
833
827
|
return ret;
|
|
834
828
|
}
|
|
835
829
|
async isUnique(collection, field, value, id) {
|
|
836
|
-
(
|
|
837
|
-
(
|
|
838
|
-
(
|
|
839
|
-
|
|
840
|
-
let _id = id
|
|
830
|
+
assert(collection);
|
|
831
|
+
assert(field);
|
|
832
|
+
assert(value);
|
|
833
|
+
log.debug('isUnuqie called', collection, field, value, id);
|
|
834
|
+
let _id = id?.toString();
|
|
841
835
|
let matches = await this.executeTransactionally(collection, async (conn) => {
|
|
842
836
|
let agg = await conn.find({ [field]: value });
|
|
843
837
|
let res = await agg.toArray();
|
|
@@ -850,13 +844,13 @@ class Mongo extends db_1.Db {
|
|
|
850
844
|
return false;
|
|
851
845
|
}
|
|
852
846
|
}
|
|
853
|
-
|
|
847
|
+
log.debug('isUnuqie returns', ret);
|
|
854
848
|
return ret;
|
|
855
849
|
}
|
|
856
850
|
async collectFieldValues(collection, field, inArray = false, opts) {
|
|
857
|
-
(
|
|
858
|
-
(
|
|
859
|
-
|
|
851
|
+
assert(collection);
|
|
852
|
+
assert(field);
|
|
853
|
+
log.debug('collectFieldValues called', collection, field);
|
|
860
854
|
let pipeline = [
|
|
861
855
|
{ $group: { _id: '$' + field } },
|
|
862
856
|
{ $sort: { _id: 1 } }
|
|
@@ -871,33 +865,33 @@ class Mongo extends db_1.Db {
|
|
|
871
865
|
let res = await agg.toArray();
|
|
872
866
|
return res;
|
|
873
867
|
}, false, { operation: "collectFieldValues", collection, field, inArray, pipeline, opts });
|
|
874
|
-
let ret = res
|
|
875
|
-
|
|
868
|
+
let ret = res?.map((v) => v._id);
|
|
869
|
+
log.debug('collectFieldValues returns', ret);
|
|
876
870
|
return ret;
|
|
877
871
|
}
|
|
878
872
|
async dropCollection(collection) {
|
|
879
|
-
(
|
|
880
|
-
|
|
873
|
+
assert(collection);
|
|
874
|
+
log.debug('dropCollection called', this.auditCollections);
|
|
881
875
|
let client = await this.connect();
|
|
882
876
|
let existing = await client.db(this.db).collections();
|
|
883
877
|
if (existing.map((c) => c.s.name).includes(collection)) {
|
|
884
878
|
await client.db(this.db).dropCollection(collection);
|
|
885
879
|
}
|
|
886
|
-
|
|
880
|
+
log.debug('dropCollection returns');
|
|
887
881
|
}
|
|
888
882
|
async resetCollectionSync(collection) {
|
|
889
|
-
(
|
|
890
|
-
|
|
883
|
+
assert(collection);
|
|
884
|
+
log.debug('resetCollectionSync called for', collection);
|
|
891
885
|
let client = await this.connect();
|
|
892
886
|
await client.db(this.db)
|
|
893
|
-
.collection(
|
|
887
|
+
.collection(SEQUENCES_COLLECTION)
|
|
894
888
|
.findOneAndDelete({ collection });
|
|
895
|
-
|
|
889
|
+
log.debug(`resetCollectionSync for ${collection} returns`);
|
|
896
890
|
}
|
|
897
891
|
async dropCollections(collections) {
|
|
898
|
-
(
|
|
899
|
-
(
|
|
900
|
-
|
|
892
|
+
assert(collections);
|
|
893
|
+
assert(collections instanceof Array);
|
|
894
|
+
log.debug('dropCollections called', this.auditCollections);
|
|
901
895
|
let client = await this.connect();
|
|
902
896
|
let existing = await client.db(this.db).collections();
|
|
903
897
|
for await (let collection of collections) {
|
|
@@ -905,12 +899,12 @@ class Mongo extends db_1.Db {
|
|
|
905
899
|
await client.db(this.db).dropCollection(collection);
|
|
906
900
|
}
|
|
907
901
|
}
|
|
908
|
-
|
|
902
|
+
log.debug('dropCollections returns');
|
|
909
903
|
}
|
|
910
904
|
async createCollections(collections) {
|
|
911
|
-
(
|
|
912
|
-
(
|
|
913
|
-
|
|
905
|
+
assert(collections);
|
|
906
|
+
assert(collections instanceof Array);
|
|
907
|
+
log.debug('createCollections called', this.auditCollections);
|
|
914
908
|
let client = await this.connect();
|
|
915
909
|
let existing = await this.getCollections();
|
|
916
910
|
for await (let collection of collections) {
|
|
@@ -918,21 +912,21 @@ class Mongo extends db_1.Db {
|
|
|
918
912
|
await client.db(this.db).createCollection(collection);
|
|
919
913
|
}
|
|
920
914
|
}
|
|
921
|
-
|
|
915
|
+
log.debug('createCollections returns');
|
|
922
916
|
}
|
|
923
917
|
async createCollection(collection) {
|
|
924
|
-
(
|
|
925
|
-
|
|
918
|
+
assert(collection);
|
|
919
|
+
log.debug('createCollection called', collection);
|
|
926
920
|
let client = await this.connect();
|
|
927
921
|
let existing = await this.getCollections();
|
|
928
922
|
if (!existing.includes(collection)) {
|
|
929
923
|
await client.db(this.db).createCollection(collection);
|
|
930
924
|
}
|
|
931
|
-
|
|
925
|
+
log.debug('createCollection returns');
|
|
932
926
|
}
|
|
933
927
|
async dbLogPurge(collection, _id) {
|
|
934
|
-
(
|
|
935
|
-
|
|
928
|
+
assert(collection);
|
|
929
|
+
log.debug('dblogPurge called', collection, _id);
|
|
936
930
|
let ret = await this.executeTransactionally(collection, async () => {
|
|
937
931
|
let cond = { db: this.db, collection, };
|
|
938
932
|
if (_id !== undefined)
|
|
@@ -941,18 +935,18 @@ class Mongo extends db_1.Db {
|
|
|
941
935
|
let ret = await client
|
|
942
936
|
.db(this.db)
|
|
943
937
|
.collection(this.auditCollectionName)
|
|
944
|
-
.deleteMany(cond,
|
|
938
|
+
.deleteMany(cond, this._sessionOpt());
|
|
945
939
|
return {
|
|
946
940
|
ok: !!ret.acknowledged,
|
|
947
941
|
n: ret.deletedCount
|
|
948
942
|
};
|
|
949
943
|
}, false, { operation: "dbLogPurge", collection, _id });
|
|
950
|
-
|
|
944
|
+
log.debug('dblogPurge returns', ret);
|
|
951
945
|
return ret;
|
|
952
946
|
}
|
|
953
947
|
async dbLogGet(collection, _id) {
|
|
954
|
-
(
|
|
955
|
-
|
|
948
|
+
assert(collection);
|
|
949
|
+
log.debug('dblogGet called', collection, _id);
|
|
956
950
|
let ret = await this.executeTransactionally(collection, async () => {
|
|
957
951
|
let cond = { db: this.db, collection };
|
|
958
952
|
if (_id)
|
|
@@ -961,12 +955,12 @@ class Mongo extends db_1.Db {
|
|
|
961
955
|
let ret = await client
|
|
962
956
|
.db(this.db)
|
|
963
957
|
.collection(this.auditCollectionName)
|
|
964
|
-
.find(cond,
|
|
958
|
+
.find(cond, this._sessionOpt())
|
|
965
959
|
.sort({ _id: -1 })
|
|
966
960
|
.toArray();
|
|
967
961
|
return ret;
|
|
968
962
|
}, false, { operation: "dbLogGet", collection, _id });
|
|
969
|
-
|
|
963
|
+
log.debug('dblogGet returns', ret);
|
|
970
964
|
return ret;
|
|
971
965
|
}
|
|
972
966
|
// HELPER FUNCTIONS
|
|
@@ -984,9 +978,9 @@ class Mongo extends db_1.Db {
|
|
|
984
978
|
return undefined;
|
|
985
979
|
if (typeof data === "symbol")
|
|
986
980
|
return data.toString();
|
|
987
|
-
if (data instanceof
|
|
981
|
+
if (data instanceof ObjectId)
|
|
988
982
|
return data;
|
|
989
|
-
if (data instanceof
|
|
983
|
+
if (data instanceof Timestamp)
|
|
990
984
|
return data;
|
|
991
985
|
if (data instanceof Date)
|
|
992
986
|
return data;
|
|
@@ -996,17 +990,17 @@ class Mongo extends db_1.Db {
|
|
|
996
990
|
return data;
|
|
997
991
|
if (data instanceof String)
|
|
998
992
|
return data;
|
|
999
|
-
if (typeof data === "string" &&
|
|
1000
|
-
return new
|
|
993
|
+
if (typeof data === "string" && data?.match(/^[0-9a-f]{24,24}$/g))
|
|
994
|
+
return new ObjectId(data);
|
|
1001
995
|
if (typeof data === "string")
|
|
1002
996
|
return data;
|
|
1003
997
|
if (data instanceof Array) {
|
|
1004
998
|
return data.map(d => this.replaceIds(d));
|
|
1005
999
|
}
|
|
1006
|
-
if (typeof data == 'object' &&
|
|
1007
|
-
return
|
|
1008
|
-
if (typeof data == 'object' &&
|
|
1009
|
-
return
|
|
1000
|
+
if (typeof data == 'object' && data?.t && data?.i !== undefined)
|
|
1001
|
+
return Base.timestamp(data);
|
|
1002
|
+
if (typeof data == 'object' && data?.high && data?.low !== undefined)
|
|
1003
|
+
return Base.timestamp(data);
|
|
1010
1004
|
if (typeof data == 'object') {
|
|
1011
1005
|
for (let key in data) {
|
|
1012
1006
|
data[key] = this.replaceIds(data[key]);
|
|
@@ -1021,7 +1015,7 @@ class Mongo extends db_1.Db {
|
|
|
1021
1015
|
}
|
|
1022
1016
|
}
|
|
1023
1017
|
async connect() {
|
|
1024
|
-
super.connect();
|
|
1018
|
+
await super.connect();
|
|
1025
1019
|
// this.session = undefined;
|
|
1026
1020
|
return this.client;
|
|
1027
1021
|
}
|
|
@@ -1029,16 +1023,16 @@ class Mongo extends db_1.Db {
|
|
|
1029
1023
|
if (this.session)
|
|
1030
1024
|
try {
|
|
1031
1025
|
await this.session.endSession();
|
|
1032
|
-
|
|
1026
|
+
log.info("session ended");
|
|
1033
1027
|
}
|
|
1034
1028
|
catch (err) {
|
|
1035
|
-
|
|
1029
|
+
log.error(`Error ending session ${err.message}`);
|
|
1036
1030
|
}
|
|
1037
1031
|
try {
|
|
1038
1032
|
await super.close();
|
|
1039
|
-
|
|
1033
|
+
log.info("connection closed");
|
|
1040
1034
|
}
|
|
1041
|
-
catch
|
|
1035
|
+
catch { /** intentionally */ }
|
|
1042
1036
|
this.session = undefined;
|
|
1043
1037
|
}
|
|
1044
1038
|
async inTransaction() {
|
|
@@ -1056,13 +1050,13 @@ class Mongo extends db_1.Db {
|
|
|
1056
1050
|
let hadSession = !!this.session;
|
|
1057
1051
|
if (!this.session) {
|
|
1058
1052
|
this.session = client.startSession();
|
|
1059
|
-
|
|
1053
|
+
log.info("session started");
|
|
1060
1054
|
}
|
|
1061
1055
|
let session = this.session;
|
|
1062
1056
|
await session.withTransaction(async () => await funct(client, session));
|
|
1063
1057
|
if (!hadSession) {
|
|
1064
1058
|
session.endSession();
|
|
1065
|
-
|
|
1059
|
+
log.info("session ended");
|
|
1066
1060
|
this.session = undefined;
|
|
1067
1061
|
}
|
|
1068
1062
|
return;
|
|
@@ -1078,24 +1072,24 @@ class Mongo extends db_1.Db {
|
|
|
1078
1072
|
try {
|
|
1079
1073
|
if (!this.session) {
|
|
1080
1074
|
this.session = client.startSession(TRANSACTION_OPTIONS);
|
|
1081
|
-
|
|
1075
|
+
log.info("session started");
|
|
1082
1076
|
}
|
|
1083
1077
|
if (!await this.inTransaction()) {
|
|
1084
1078
|
await this.session.startTransaction();
|
|
1085
|
-
|
|
1079
|
+
log.info("transaction started");
|
|
1086
1080
|
}
|
|
1087
1081
|
}
|
|
1088
1082
|
catch (err) {
|
|
1089
|
-
|
|
1083
|
+
log.error('startTransaction error', err);
|
|
1090
1084
|
try {
|
|
1091
1085
|
if (this.session) {
|
|
1092
1086
|
await this.session.endSession();
|
|
1093
|
-
|
|
1087
|
+
log.info("session ended");
|
|
1094
1088
|
}
|
|
1095
1089
|
this.session = undefined;
|
|
1096
1090
|
}
|
|
1097
1091
|
catch (e) {
|
|
1098
|
-
|
|
1092
|
+
log.error("startTransaction - error in endSession", e.message || e);
|
|
1099
1093
|
}
|
|
1100
1094
|
return;
|
|
1101
1095
|
}
|
|
@@ -1108,13 +1102,13 @@ class Mongo extends db_1.Db {
|
|
|
1108
1102
|
return;
|
|
1109
1103
|
let session = this.session;
|
|
1110
1104
|
await session.commitTransaction();
|
|
1111
|
-
|
|
1105
|
+
log.info("transaction committed");
|
|
1112
1106
|
session.endSession();
|
|
1113
1107
|
this.session = undefined;
|
|
1114
|
-
|
|
1108
|
+
log.info("session ended");
|
|
1115
1109
|
}
|
|
1116
1110
|
catch (err) {
|
|
1117
|
-
|
|
1111
|
+
log.error(`commitTransaction error ${err.message || err}`);
|
|
1118
1112
|
}
|
|
1119
1113
|
}
|
|
1120
1114
|
async abortTransaction() {
|
|
@@ -1125,13 +1119,13 @@ class Mongo extends db_1.Db {
|
|
|
1125
1119
|
return;
|
|
1126
1120
|
let session = this.session;
|
|
1127
1121
|
await session.abortTransaction();
|
|
1128
|
-
|
|
1122
|
+
log.info("transaction aborted");
|
|
1129
1123
|
await session.endSession();
|
|
1130
1124
|
this.session = undefined;
|
|
1131
|
-
|
|
1125
|
+
log.info("session ended");
|
|
1132
1126
|
}
|
|
1133
1127
|
catch (err) {
|
|
1134
|
-
|
|
1128
|
+
log.error(`abortTransaction error ${err.message || err}`);
|
|
1135
1129
|
}
|
|
1136
1130
|
}
|
|
1137
1131
|
async _try_once(useTransaction, f, collection) {
|
|
@@ -1155,7 +1149,7 @@ class Mongo extends db_1.Db {
|
|
|
1155
1149
|
if (useTransaction)
|
|
1156
1150
|
await this.abortTransaction();
|
|
1157
1151
|
}
|
|
1158
|
-
catch
|
|
1152
|
+
catch { /* intentionally */ }
|
|
1159
1153
|
throw err;
|
|
1160
1154
|
}
|
|
1161
1155
|
}
|
|
@@ -1168,9 +1162,9 @@ class Mongo extends db_1.Db {
|
|
|
1168
1162
|
return await this._try_once(useTransaction, f, collection);
|
|
1169
1163
|
}
|
|
1170
1164
|
catch (err) {
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1165
|
+
log.error(`Mongo command has failed for ${this.db}.${collection} - ${(this.session ? "ROLLBACK - " : "")} ${err.message || err}`);
|
|
1166
|
+
log.error(debugObject);
|
|
1167
|
+
log.debug(err);
|
|
1174
1168
|
let x = (err || "").toString();
|
|
1175
1169
|
console.log('x');
|
|
1176
1170
|
let isRepeatable = x.match(/Topology is closed, please connect/i)
|
|
@@ -1179,21 +1173,21 @@ class Mongo extends db_1.Db {
|
|
|
1179
1173
|
|| x.match(/Topology closed/);
|
|
1180
1174
|
if (isRepeatable) {
|
|
1181
1175
|
try {
|
|
1182
|
-
|
|
1176
|
+
log.error("Trying to reopen connection and repeat as");
|
|
1183
1177
|
await this.close();
|
|
1184
1178
|
// a single retry
|
|
1185
1179
|
await super.connect();
|
|
1186
1180
|
let ret = await this._try_once(useTransaction, f, collection);
|
|
1187
|
-
|
|
1188
|
-
|
|
1181
|
+
log.error("OK - Retry succeeded.");
|
|
1182
|
+
log.error("");
|
|
1189
1183
|
return ret;
|
|
1190
1184
|
}
|
|
1191
1185
|
catch (err2) {
|
|
1192
1186
|
/* intentional */
|
|
1193
1187
|
if (debugObject)
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1188
|
+
log.error(debugObject);
|
|
1189
|
+
log.error(`FAIL - Retry failed: ${err2.message || err2}`);
|
|
1190
|
+
log.error("");
|
|
1197
1191
|
}
|
|
1198
1192
|
}
|
|
1199
1193
|
throw err;
|
|
@@ -1201,41 +1195,40 @@ class Mongo extends db_1.Db {
|
|
|
1201
1195
|
}
|
|
1202
1196
|
async _findLastSequenceForKey(connection, key) {
|
|
1203
1197
|
let maxfld = await (connection
|
|
1204
|
-
.find({},
|
|
1198
|
+
.find({}, this._sessionOpt())
|
|
1205
1199
|
.sort({ [key]: -1 })
|
|
1206
1200
|
.limit(1)
|
|
1207
1201
|
.toArray());
|
|
1208
1202
|
if (maxfld.length === 0)
|
|
1209
1203
|
return undefined;
|
|
1210
|
-
return parseInt(maxfld[0][key]) || 0;
|
|
1204
|
+
return parseInt(maxfld?.[0]?.[key]) || 0;
|
|
1211
1205
|
}
|
|
1212
1206
|
async _getNextCollectionUpdateSeqNo(collection, conn) {
|
|
1213
|
-
var _a;
|
|
1214
1207
|
let opts = {
|
|
1215
1208
|
upsert: true,
|
|
1216
1209
|
returnDocument: "after",
|
|
1217
1210
|
};
|
|
1218
1211
|
let nextSeq = await (conn.db(this.db)
|
|
1219
|
-
.collection(
|
|
1212
|
+
.collection(SEQUENCES_COLLECTION)
|
|
1220
1213
|
.findOneAndUpdate({ collection }, {
|
|
1221
1214
|
$inc: { seq: 1 },
|
|
1222
1215
|
$currentDate: { last: { $type: "date" }, ts: { $type: "timestamp" } }
|
|
1223
1216
|
}, opts));
|
|
1224
1217
|
conn.db(this.db).collection(collection);
|
|
1225
|
-
return
|
|
1218
|
+
return nextSeq?.value?.seq || 1;
|
|
1226
1219
|
}
|
|
1227
1220
|
_findSequenceKeys(object) {
|
|
1228
1221
|
if (!object)
|
|
1229
1222
|
return;
|
|
1230
1223
|
let seqKeys = Object.keys(object).filter(key => object[key] === 'SEQ_NEXT' || object[key] === 'SEQ_LAST');
|
|
1231
|
-
return (
|
|
1224
|
+
return (seqKeys?.length > 0 || this.syncSupport) ? { seqKeys } : undefined;
|
|
1232
1225
|
}
|
|
1233
1226
|
async _processSequenceField(client, collection, insert, seqKeys) {
|
|
1234
|
-
(
|
|
1227
|
+
assert(this.client);
|
|
1235
1228
|
if (this.syncSupport) {
|
|
1236
1229
|
insert._csq = (await this._getNextCollectionUpdateSeqNo(collection, client));
|
|
1237
1230
|
}
|
|
1238
|
-
for await (let seqKey of
|
|
1231
|
+
for await (let seqKey of seqKeys?.seqKeys || []) {
|
|
1239
1232
|
let last = await this._findLastSequenceForKey(client.db(this.db).collection(collection), seqKey);
|
|
1240
1233
|
if (last === undefined) {
|
|
1241
1234
|
await this.createCollection(collection);
|
|
@@ -1247,21 +1240,21 @@ class Mongo extends db_1.Db {
|
|
|
1247
1240
|
return insert;
|
|
1248
1241
|
}
|
|
1249
1242
|
async _processSequenceFieldForMany(connection, collection, inserts) {
|
|
1250
|
-
(
|
|
1251
|
-
(
|
|
1252
|
-
if (!
|
|
1243
|
+
assert(this.client);
|
|
1244
|
+
assert(connection);
|
|
1245
|
+
if (!inserts?.length)
|
|
1253
1246
|
return;
|
|
1254
1247
|
let seqKeys = this._findSequenceKeys(inserts[0]);
|
|
1255
1248
|
let seq = 0;
|
|
1256
1249
|
if (this.syncSupport)
|
|
1257
1250
|
seq = await this._getNextCollectionUpdateSeqNo(collection, connection);
|
|
1258
|
-
for await (let seqKey of
|
|
1251
|
+
for await (let seqKey of seqKeys?.seqKeys || []) {
|
|
1259
1252
|
let last = await this._findLastSequenceForKey(connection.db(this.db).collection(collection), seqKey);
|
|
1260
1253
|
if (last === undefined) {
|
|
1261
1254
|
try {
|
|
1262
1255
|
await this.createCollection(collection);
|
|
1263
1256
|
}
|
|
1264
|
-
catch
|
|
1257
|
+
catch { /* intentionaly */ }
|
|
1265
1258
|
last = 0;
|
|
1266
1259
|
}
|
|
1267
1260
|
for (let insert of inserts) {
|
|
@@ -1312,7 +1305,7 @@ class Mongo extends db_1.Db {
|
|
|
1312
1305
|
async _publishAndAudit(operation, db, collection, dataToPublish, noEmit) {
|
|
1313
1306
|
if (!dataToPublish._id && !["deleteMany", "updateMany"].includes(operation))
|
|
1314
1307
|
throw new Error(`_publishAndAudit requires _id for ${operation}`);
|
|
1315
|
-
let data = (
|
|
1308
|
+
let data = cloneDeep(dataToPublish);
|
|
1316
1309
|
if (data._id && /[0-9a-f]{24,24}/i.test(data._id.toString()))
|
|
1317
1310
|
data._id = data._id.toHexString();
|
|
1318
1311
|
let toPublish = undefined;
|
|
@@ -1343,7 +1336,7 @@ class Mongo extends db_1.Db {
|
|
|
1343
1336
|
return toPublish;
|
|
1344
1337
|
}
|
|
1345
1338
|
emit(what) {
|
|
1346
|
-
|
|
1339
|
+
log.debug("emitting publish", what);
|
|
1347
1340
|
this.emitter.emit('publish', what);
|
|
1348
1341
|
}
|
|
1349
1342
|
async _writeAuditRecord(collection, operation, data, user = this.user, audit = this.audit) {
|
|
@@ -1354,7 +1347,7 @@ class Mongo extends db_1.Db {
|
|
|
1354
1347
|
{ $match: { entityid: Mongo._toId(data._id) } },
|
|
1355
1348
|
{ $sort: { rev: -1 } },
|
|
1356
1349
|
{ $limit: 1 }
|
|
1357
|
-
], { session: this.session })).toArray();
|
|
1350
|
+
], this.session ? { session: this.session } : {})).toArray();
|
|
1358
1351
|
let previousAuditRecord = previousAuditRecords.length ? previousAuditRecords[0] : { rev: 0, changes: {} };
|
|
1359
1352
|
if (previousAuditRecords.length === 0)
|
|
1360
1353
|
await this.createCollection(this.auditCollectionName);
|
|
@@ -1363,9 +1356,9 @@ class Mongo extends db_1.Db {
|
|
|
1363
1356
|
let auditRecord = {
|
|
1364
1357
|
db: this.db,
|
|
1365
1358
|
collection: collection,
|
|
1366
|
-
entityid:
|
|
1367
|
-
rev: previousAuditRecord
|
|
1368
|
-
ts:
|
|
1359
|
+
entityid: Base.objectid(data._id),
|
|
1360
|
+
rev: (previousAuditRecord?.rev || 0) + 1,
|
|
1361
|
+
ts: Base.timestamp(),
|
|
1369
1362
|
on: new Date(),
|
|
1370
1363
|
operation: operation,
|
|
1371
1364
|
changes: dataNoId,
|
|
@@ -1374,11 +1367,14 @@ class Mongo extends db_1.Db {
|
|
|
1374
1367
|
auditRecord.user = user;
|
|
1375
1368
|
if (audit)
|
|
1376
1369
|
auditRecord.audit = audit;
|
|
1377
|
-
|
|
1370
|
+
log.trace('AUDITING', auditRecord);
|
|
1378
1371
|
let ret = await client.db(this.db)
|
|
1379
1372
|
.collection(this.auditCollectionName)
|
|
1380
|
-
.insertOne(auditRecord,
|
|
1381
|
-
|
|
1373
|
+
.insertOne(auditRecord, this._sessionOpt());
|
|
1374
|
+
log.debug('AUDITED', auditRecord, ret.insertedId);
|
|
1375
|
+
}
|
|
1376
|
+
_sessionOpt() {
|
|
1377
|
+
return this.session ? { session: this.session } : {};
|
|
1382
1378
|
}
|
|
1383
1379
|
async _processUpdateObject(update) {
|
|
1384
1380
|
await this._processHashedKeys(update);
|
|
@@ -1417,8 +1413,8 @@ class Mongo extends db_1.Db {
|
|
|
1417
1413
|
for await (let key of Object.keys(update)) {
|
|
1418
1414
|
let shouldBeHashed = /^__hashed_(.+)$/.test(key);
|
|
1419
1415
|
if (shouldBeHashed) {
|
|
1420
|
-
let salt = await
|
|
1421
|
-
let hash = await
|
|
1416
|
+
let salt = await bcrypt.genSalt(saltRounds);
|
|
1417
|
+
let hash = await bcrypt.hash(update[key], salt);
|
|
1422
1418
|
update[key] = { salt, hash };
|
|
1423
1419
|
}
|
|
1424
1420
|
}
|
|
@@ -1442,6 +1438,4 @@ class Mongo extends db_1.Db {
|
|
|
1442
1438
|
return ret;
|
|
1443
1439
|
}
|
|
1444
1440
|
}
|
|
1445
|
-
exports.default = Mongo;
|
|
1446
1441
|
module.exports = Mongo;
|
|
1447
|
-
//# sourceMappingURL=mongo.js.map
|