cosa 6.3.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/lib/db.js +1 -0
- package/lib/model.js +65 -22
- package/lib/utils.js +1 -1
- package/package.json +10 -10
package/LICENSE
CHANGED
package/lib/db.js
CHANGED
|
@@ -342,6 +342,7 @@ class Database extends EventEmitter {
|
|
|
342
342
|
* @see {@link https://mongodb.github.io/node-mongodb-native/4.0/interfaces/aggregateoptions.html#maxtimems}
|
|
343
343
|
*/
|
|
344
344
|
async aggregate(collectionName, pipeline, options = {}) {
|
|
345
|
+
pipeline = deserialize(pipeline);
|
|
345
346
|
const collection = await this.collection(collectionName);
|
|
346
347
|
return collection.aggregate(pipeline, {
|
|
347
348
|
readPreference: options.readPreference,
|
package/lib/model.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const joi = require('
|
|
1
|
+
const joi = require('joi');
|
|
2
2
|
const etag = require('etag');
|
|
3
3
|
const debug = require('debug')('cosa:model');
|
|
4
4
|
const objectPath = require('object-path');
|
|
@@ -7,7 +7,9 @@ const { EJSON } = require('bson');
|
|
|
7
7
|
const Cursor = require('./cursor');
|
|
8
8
|
const errors = require('./errors');
|
|
9
9
|
const { ObjectId } = require('bson');
|
|
10
|
-
const {
|
|
10
|
+
const {
|
|
11
|
+
pathEq, complement, pick, omit, has, isEmpty, isPlainObject
|
|
12
|
+
} = require('omnibelt');
|
|
11
13
|
const { buildPropertySchema } = require('./utils');
|
|
12
14
|
const Immutable = require('./immutable');
|
|
13
15
|
Immutable.use(require('./defined-object'));
|
|
@@ -23,6 +25,16 @@ const db = require('./db');
|
|
|
23
25
|
// functions that are defined later on.
|
|
24
26
|
let _serialize, _extend;
|
|
25
27
|
|
|
28
|
+
const shouldWait = (waitType) => {
|
|
29
|
+
return (options, definition) => {
|
|
30
|
+
if (has(waitType, options)) { return options[waitType]; }
|
|
31
|
+
return definition[waitType];
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const shouldWaitAfterSave = shouldWait('waitAfterSave');
|
|
36
|
+
const shouldWaitAfterRemove = shouldWait('waitAfterRemove');
|
|
37
|
+
|
|
26
38
|
const addVirtuals = (def, obj) => {
|
|
27
39
|
if (def.type === 'array' && def.items && Array.isArray(obj)) {
|
|
28
40
|
for (let i = 0, l = obj.length; i < l; i++) {
|
|
@@ -177,7 +189,7 @@ const _create = (data, definition) => {
|
|
|
177
189
|
if ('function' === typeof newOrUpdatedModel.afterSaveCommit) {
|
|
178
190
|
chain = chain.then(() => newOrUpdatedModel.afterSaveCommit(original, options));
|
|
179
191
|
}
|
|
180
|
-
if (options
|
|
192
|
+
if (shouldWaitAfterSave(options, definition)) {
|
|
181
193
|
await chain;
|
|
182
194
|
}
|
|
183
195
|
}
|
|
@@ -233,11 +245,16 @@ const _create = (data, definition) => {
|
|
|
233
245
|
});
|
|
234
246
|
};
|
|
235
247
|
|
|
236
|
-
definition.methods.del = function(
|
|
248
|
+
definition.methods.del = function(toDelete) {
|
|
237
249
|
const original = this;
|
|
238
250
|
return this.mutate(function() {
|
|
239
|
-
|
|
240
|
-
|
|
251
|
+
if (!Array.isArray(toDelete)) {
|
|
252
|
+
toDelete = [toDelete];
|
|
253
|
+
}
|
|
254
|
+
toDelete.forEach((path) => {
|
|
255
|
+
objectPath.del(this, path);
|
|
256
|
+
});
|
|
257
|
+
_markAsModified(this, toDelete, original);
|
|
241
258
|
});
|
|
242
259
|
};
|
|
243
260
|
|
|
@@ -333,7 +350,7 @@ const _create = (data, definition) => {
|
|
|
333
350
|
if ('function' === typeof this.afterRemoveCommit) {
|
|
334
351
|
chain = chain.then(() => this.afterRemoveCommit(options));
|
|
335
352
|
}
|
|
336
|
-
if (options
|
|
353
|
+
if (shouldWaitAfterRemove(options, definition)) {
|
|
337
354
|
await chain;
|
|
338
355
|
}
|
|
339
356
|
}
|
|
@@ -399,9 +416,17 @@ const define = (definition) => {
|
|
|
399
416
|
|
|
400
417
|
definition._schema = _buildSchema(definition);
|
|
401
418
|
|
|
402
|
-
const
|
|
419
|
+
const makeSafeQuery = (query, options) => {
|
|
420
|
+
if (!query || !isPlainObject(query)) {
|
|
421
|
+
throw new Error('Query must be an object.');
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if (!options.allowGlobalQuery && isEmpty(query)) {
|
|
425
|
+
throw new Error('To make an unrestricted query, please set the allowGlobalQuery option.');
|
|
426
|
+
}
|
|
427
|
+
|
|
403
428
|
return options.bypassGlobalWhere || !definition.where ?
|
|
404
|
-
query : { ...definition.where, ...
|
|
429
|
+
query : { ...definition.where, ...query };
|
|
405
430
|
};
|
|
406
431
|
|
|
407
432
|
return {
|
|
@@ -422,15 +447,15 @@ const define = (definition) => {
|
|
|
422
447
|
return Immutable.isImmutableType(obj, definition.name || 'object');
|
|
423
448
|
},
|
|
424
449
|
|
|
425
|
-
count: (query, options = {}) => {
|
|
426
|
-
query =
|
|
450
|
+
count: async (query, options = {}) => {
|
|
451
|
+
query = makeSafeQuery(query, options);
|
|
427
452
|
const collection = definition.collection;
|
|
428
453
|
debug(`counting ${JSON.stringify(query)} in ${collection}`);
|
|
429
454
|
return db.find(collection, query, { ...options, count: true });
|
|
430
455
|
},
|
|
431
456
|
|
|
432
457
|
find: async (query, options = {}) => {
|
|
433
|
-
query =
|
|
458
|
+
query = makeSafeQuery(query, options);
|
|
434
459
|
const collection = definition.collection;
|
|
435
460
|
debug(`finding ${JSON.stringify(query)} in ${collection}`);
|
|
436
461
|
const dbCursor = await db.find(collection, query, options);
|
|
@@ -440,16 +465,22 @@ const define = (definition) => {
|
|
|
440
465
|
return options.array ? cursor.toArray() : cursor;
|
|
441
466
|
},
|
|
442
467
|
|
|
468
|
+
exists: async (query, options = {}) => {
|
|
469
|
+
query = makeSafeQuery(query, options);
|
|
470
|
+
const collection = definition.collection;
|
|
471
|
+
return !!(await db.find(collection, query, { ...options, count: true, limit: 1 }));
|
|
472
|
+
},
|
|
473
|
+
|
|
443
474
|
findOne: async (query, options = {}) => {
|
|
444
|
-
query =
|
|
475
|
+
query = makeSafeQuery(query, options);
|
|
445
476
|
const collection = definition.collection;
|
|
446
477
|
debug(`finding one${JSON.stringify(query)} in ${collection}`);
|
|
447
478
|
const result = await db.find(collection, query, { ...options, findOne: true });
|
|
448
479
|
return !result ? null : _create(result, definition);
|
|
449
480
|
},
|
|
450
481
|
|
|
451
|
-
update: (query, update, { autoSet = true, ...options } = {}) => {
|
|
452
|
-
query =
|
|
482
|
+
update: async (query, update, { autoSet = true, ...options } = {}) => {
|
|
483
|
+
query = makeSafeQuery(query, options);
|
|
453
484
|
const collection = definition.collection;
|
|
454
485
|
if (autoSet) {
|
|
455
486
|
update = { $set: update };
|
|
@@ -458,28 +489,40 @@ const define = (definition) => {
|
|
|
458
489
|
return db.update(collection, query, update, options);
|
|
459
490
|
},
|
|
460
491
|
|
|
461
|
-
remove: (query, options = {}) => {
|
|
462
|
-
query =
|
|
492
|
+
remove: async (query, options = {}) => {
|
|
493
|
+
query = makeSafeQuery(query, options);
|
|
463
494
|
const collection = definition.collection;
|
|
464
495
|
debug(`removing ${JSON.stringify(query)} from ${collection}`);
|
|
465
496
|
return db.remove(collection, query, options);
|
|
466
497
|
},
|
|
467
498
|
|
|
468
|
-
distinct: (key, query, options = {}) => {
|
|
469
|
-
query =
|
|
499
|
+
distinct: async (key, query, options = {}) => {
|
|
500
|
+
query = makeSafeQuery(query, options);
|
|
470
501
|
const collection = definition.collection;
|
|
471
502
|
debug(`finding distinct "${key}" ${JSON.stringify(query)} from ${collection}`);
|
|
472
503
|
return db.distinct(collection, key, query, options);
|
|
473
504
|
},
|
|
474
505
|
|
|
475
|
-
aggregate: (pipeline, options = {}) => {
|
|
506
|
+
aggregate: async (pipeline, options = {}) => {
|
|
507
|
+
if (!Array.isArray(pipeline)) {
|
|
508
|
+
throw new Error('Aggregation pipeline must be an array.');
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
pipeline = pipeline.slice();
|
|
512
|
+
if (pipeline[0]?.$match) {
|
|
513
|
+
pipeline[0] = { ...pipeline[0], $match: makeSafeQuery(pipeline[0].$match, options) };
|
|
514
|
+
} else {
|
|
515
|
+
pipeline.unshift({ $match: makeSafeQuery({}, options) });
|
|
516
|
+
}
|
|
517
|
+
|
|
476
518
|
const collection = definition.collection;
|
|
477
519
|
debug(`aggregating ${JSON.stringify(pipeline)} from ${collection}`);
|
|
478
|
-
|
|
520
|
+
const dbCursor = await db.aggregate(collection, pipeline, options);
|
|
521
|
+
return options.array ? dbCursor.toArray() : dbCursor;
|
|
479
522
|
},
|
|
480
523
|
|
|
481
524
|
project: async (query, value, options = {}) => {
|
|
482
|
-
query =
|
|
525
|
+
query = makeSafeQuery(query, options);
|
|
483
526
|
const collection = definition.collection;
|
|
484
527
|
debug(`project ${value}, ${JSON.stringify(query)} in ${collection}`);
|
|
485
528
|
let dbCursor = await db.find(collection, query, options);
|
package/lib/utils.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cosa",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0",
|
|
4
4
|
"description": "Cosa Models for MongoDB",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"engines": {
|
|
@@ -35,25 +35,25 @@
|
|
|
35
35
|
"lib"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"bson": "~4.7.
|
|
38
|
+
"bson": "~4.7.2",
|
|
39
39
|
"clone": "^2.1.2",
|
|
40
40
|
"debug": "^4.3.4",
|
|
41
41
|
"error": "^7.0.2",
|
|
42
42
|
"etag": "^1.8.1",
|
|
43
|
-
"
|
|
44
|
-
"mongodb": "~4.
|
|
43
|
+
"joi": "^17.8.3",
|
|
44
|
+
"mongodb": "~4.14.0",
|
|
45
45
|
"object-path": "^0.11.8",
|
|
46
46
|
"omnibelt": "^2.1.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@losant/eslint-config-losant": "^1.
|
|
50
|
-
"husky": "^8.0.
|
|
51
|
-
"lint-staged": "^13.
|
|
52
|
-
"chai": "^4.3.
|
|
49
|
+
"@losant/eslint-config-losant": "^1.6.0",
|
|
50
|
+
"husky": "^8.0.3",
|
|
51
|
+
"lint-staged": "^13.1.2",
|
|
52
|
+
"chai": "^4.3.7",
|
|
53
53
|
"chai-as-promised": "^7.1.1",
|
|
54
54
|
"chai-datetime": "^1.8.0",
|
|
55
|
-
"documentation": "^14.0.
|
|
56
|
-
"mocha": "^10.
|
|
55
|
+
"documentation": "^14.0.1",
|
|
56
|
+
"mocha": "^10.2.0",
|
|
57
57
|
"string-template": "^1.0.0"
|
|
58
58
|
},
|
|
59
59
|
"eslintConfig": {
|