mongoose 8.9.5 → 8.9.7
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/browser.umd.js +1 -1
- package/lib/aggregate.js +12 -0
- package/lib/cast/uuid.js +78 -0
- package/lib/document.js +2 -2
- package/lib/helpers/document/applyDefaults.js +3 -0
- package/lib/schema/uuid.js +3 -70
- package/package.json +8 -8
- package/types/expressions.d.ts +15 -0
- package/valnotes.md +0 -85
package/lib/aggregate.js
CHANGED
|
@@ -392,11 +392,23 @@ Aggregate.prototype.project = function(arg) {
|
|
|
392
392
|
* @memberOf Aggregate
|
|
393
393
|
* @instance
|
|
394
394
|
* @param {Object} arg
|
|
395
|
+
* @param {Object|Array<Number>} arg.near GeoJSON point or coordinates array
|
|
395
396
|
* @return {Aggregate}
|
|
396
397
|
* @api public
|
|
397
398
|
*/
|
|
398
399
|
|
|
399
400
|
Aggregate.prototype.near = function(arg) {
|
|
401
|
+
if (arg == null) {
|
|
402
|
+
throw new MongooseError('Aggregate `near()` must be called with non-nullish argument');
|
|
403
|
+
}
|
|
404
|
+
if (arg.near == null) {
|
|
405
|
+
throw new MongooseError('Aggregate `near()` argument must have a `near` property');
|
|
406
|
+
}
|
|
407
|
+
const coordinates = Array.isArray(arg.near) ? arg.near : arg.near.coordinates;
|
|
408
|
+
if (typeof arg.near === 'object' && (!Array.isArray(coordinates) || coordinates.length < 2 || coordinates.find(c => typeof c !== 'number'))) {
|
|
409
|
+
throw new MongooseError(`Aggregate \`near()\` argument has invalid coordinates, got "${coordinates}"`);
|
|
410
|
+
}
|
|
411
|
+
|
|
400
412
|
const op = {};
|
|
401
413
|
op.$geoNear = arg;
|
|
402
414
|
return this.append(op);
|
package/lib/cast/uuid.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const MongooseBuffer = require('../types/buffer');
|
|
4
|
+
|
|
5
|
+
const UUID_FORMAT = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i;
|
|
6
|
+
const Binary = MongooseBuffer.Binary;
|
|
7
|
+
|
|
8
|
+
module.exports = function castUUID(value) {
|
|
9
|
+
if (value == null) {
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function newBuffer(initbuff) {
|
|
14
|
+
const buff = new MongooseBuffer(initbuff);
|
|
15
|
+
buff._subtype = 4;
|
|
16
|
+
return buff;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (typeof value === 'string') {
|
|
20
|
+
if (UUID_FORMAT.test(value)) {
|
|
21
|
+
return stringToBinary(value);
|
|
22
|
+
} else {
|
|
23
|
+
throw new Error(`"${value}" is not a valid UUID string`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (Buffer.isBuffer(value)) {
|
|
28
|
+
return newBuffer(value);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (value instanceof Binary) {
|
|
32
|
+
return newBuffer(value.value(true));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Re: gh-647 and gh-3030, we're ok with casting using `toString()`
|
|
36
|
+
// **unless** its the default Object.toString, because "[object Object]"
|
|
37
|
+
// doesn't really qualify as useful data
|
|
38
|
+
if (value.toString && value.toString !== Object.prototype.toString) {
|
|
39
|
+
if (UUID_FORMAT.test(value.toString())) {
|
|
40
|
+
return stringToBinary(value.toString());
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
throw new Error(`"${value}" cannot be casted to a UUID`);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
module.exports.UUID_FORMAT = UUID_FORMAT;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Helper function to convert the input hex-string to a buffer
|
|
51
|
+
* @param {String} hex The hex string to convert
|
|
52
|
+
* @returns {Buffer} The hex as buffer
|
|
53
|
+
* @api private
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
function hex2buffer(hex) {
|
|
57
|
+
// use buffer built-in function to convert from hex-string to buffer
|
|
58
|
+
const buff = hex != null && Buffer.from(hex, 'hex');
|
|
59
|
+
return buff;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Convert a String to Binary
|
|
64
|
+
* @param {String} uuidStr The value to process
|
|
65
|
+
* @returns {MongooseBuffer} The binary to store
|
|
66
|
+
* @api private
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
function stringToBinary(uuidStr) {
|
|
70
|
+
// Protect against undefined & throwing err
|
|
71
|
+
if (typeof uuidStr !== 'string') uuidStr = '';
|
|
72
|
+
const hex = uuidStr.replace(/[{}-]/g, ''); // remove extra characters
|
|
73
|
+
const bytes = hex2buffer(hex);
|
|
74
|
+
const buff = new MongooseBuffer(bytes);
|
|
75
|
+
buff._subtype = 4;
|
|
76
|
+
|
|
77
|
+
return buff;
|
|
78
|
+
}
|
package/lib/document.js
CHANGED
|
@@ -1147,7 +1147,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
|
|
|
1147
1147
|
} else if (pathtype === 'nested' && valForKey == null) {
|
|
1148
1148
|
this.$set(pathName, valForKey, constructing, options);
|
|
1149
1149
|
}
|
|
1150
|
-
} else
|
|
1150
|
+
} else {
|
|
1151
1151
|
this.$set(pathName, valForKey, constructing, options);
|
|
1152
1152
|
}
|
|
1153
1153
|
}
|
|
@@ -4069,7 +4069,7 @@ Document.prototype.$__toObjectShallow = function $__toObjectShallow() {
|
|
|
4069
4069
|
* @param {Boolean} [options.flattenMaps=false] if true, convert Maps to POJOs. Useful if you want to `JSON.stringify()` the result of `toObject()`.
|
|
4070
4070
|
* @param {Boolean} [options.flattenObjectIds=false] if true, convert any ObjectIds in the result to 24 character hex strings.
|
|
4071
4071
|
* @param {Boolean} [options.useProjection=false] - If true, omits fields that are excluded in this document's projection. Unless you specified a projection, this will omit any field that has `select: false` in the schema.
|
|
4072
|
-
* @return {Object}
|
|
4072
|
+
* @return {Object} document as a plain old JavaScript object (POJO). This object may contain ObjectIds, Maps, Dates, mongodb.Binary, Buffers, and other non-POJO values.
|
|
4073
4073
|
* @see mongodb.Binary https://mongodb.github.io/node-mongodb-native/4.9/classes/Binary.html
|
|
4074
4074
|
* @api public
|
|
4075
4075
|
* @memberOf Document
|
|
@@ -19,6 +19,9 @@ module.exports = function applyDefaults(doc, fields, exclude, hasIncludedChildre
|
|
|
19
19
|
const type = doc.$__schema.paths[p];
|
|
20
20
|
const path = type.splitPath();
|
|
21
21
|
const len = path.length;
|
|
22
|
+
if (path[len - 1] === '$*') {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
22
25
|
let included = false;
|
|
23
26
|
let doc_ = doc._doc;
|
|
24
27
|
for (let j = 0; j < len; ++j) {
|
package/lib/schema/uuid.js
CHANGED
|
@@ -7,43 +7,13 @@
|
|
|
7
7
|
const MongooseBuffer = require('../types/buffer');
|
|
8
8
|
const SchemaType = require('../schemaType');
|
|
9
9
|
const CastError = SchemaType.CastError;
|
|
10
|
+
const castUUID = require('../cast/uuid');
|
|
10
11
|
const utils = require('../utils');
|
|
11
12
|
const handleBitwiseOperator = require('./operators/bitwise');
|
|
12
13
|
|
|
13
|
-
const UUID_FORMAT =
|
|
14
|
+
const UUID_FORMAT = castUUID.UUID_FORMAT;
|
|
14
15
|
const Binary = MongooseBuffer.Binary;
|
|
15
16
|
|
|
16
|
-
/**
|
|
17
|
-
* Helper function to convert the input hex-string to a buffer
|
|
18
|
-
* @param {String} hex The hex string to convert
|
|
19
|
-
* @returns {Buffer} The hex as buffer
|
|
20
|
-
* @api private
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
function hex2buffer(hex) {
|
|
24
|
-
// use buffer built-in function to convert from hex-string to buffer
|
|
25
|
-
const buff = hex != null && Buffer.from(hex, 'hex');
|
|
26
|
-
return buff;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Convert a String to Binary
|
|
31
|
-
* @param {String} uuidStr The value to process
|
|
32
|
-
* @returns {MongooseBuffer} The binary to store
|
|
33
|
-
* @api private
|
|
34
|
-
*/
|
|
35
|
-
|
|
36
|
-
function stringToBinary(uuidStr) {
|
|
37
|
-
// Protect against undefined & throwing err
|
|
38
|
-
if (typeof uuidStr !== 'string') uuidStr = '';
|
|
39
|
-
const hex = uuidStr.replace(/[{}-]/g, ''); // remove extra characters
|
|
40
|
-
const bytes = hex2buffer(hex);
|
|
41
|
-
const buff = new MongooseBuffer(bytes);
|
|
42
|
-
buff._subtype = 4;
|
|
43
|
-
|
|
44
|
-
return buff;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
17
|
/**
|
|
48
18
|
* Convert binary to a uuid string
|
|
49
19
|
* @param {Buffer|Binary|String} uuidBin The value to process
|
|
@@ -109,44 +79,7 @@ SchemaUUID.prototype.constructor = SchemaUUID;
|
|
|
109
79
|
* ignore
|
|
110
80
|
*/
|
|
111
81
|
|
|
112
|
-
SchemaUUID._cast =
|
|
113
|
-
if (value == null) {
|
|
114
|
-
return value;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function newBuffer(initbuff) {
|
|
118
|
-
const buff = new MongooseBuffer(initbuff);
|
|
119
|
-
buff._subtype = 4;
|
|
120
|
-
return buff;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (typeof value === 'string') {
|
|
124
|
-
if (UUID_FORMAT.test(value)) {
|
|
125
|
-
return stringToBinary(value);
|
|
126
|
-
} else {
|
|
127
|
-
throw new CastError(SchemaUUID.schemaName, value, this.path);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (Buffer.isBuffer(value)) {
|
|
132
|
-
return newBuffer(value);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (value instanceof Binary) {
|
|
136
|
-
return newBuffer(value.value(true));
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Re: gh-647 and gh-3030, we're ok with casting using `toString()`
|
|
140
|
-
// **unless** its the default Object.toString, because "[object Object]"
|
|
141
|
-
// doesn't really qualify as useful data
|
|
142
|
-
if (value.toString && value.toString !== Object.prototype.toString) {
|
|
143
|
-
if (UUID_FORMAT.test(value.toString())) {
|
|
144
|
-
return stringToBinary(value.toString());
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
throw new CastError(SchemaUUID.schemaName, value, this.path);
|
|
149
|
-
};
|
|
82
|
+
SchemaUUID._cast = castUUID;
|
|
150
83
|
|
|
151
84
|
/**
|
|
152
85
|
* Attaches a getter for all UUID instances.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mongoose",
|
|
3
3
|
"description": "Mongoose MongoDB ODM",
|
|
4
|
-
"version": "8.9.
|
|
4
|
+
"version": "8.9.7",
|
|
5
5
|
"author": "Guillermo Rauch <guillermo@learnboost.com>",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mongodb",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"sift": "17.1.3"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@babel/core": "7.26.
|
|
32
|
-
"@babel/preset-env": "7.26.
|
|
31
|
+
"@babel/core": "7.26.7",
|
|
32
|
+
"@babel/preset-env": "7.26.7",
|
|
33
33
|
"@typescript-eslint/eslint-plugin": "^8.19.1",
|
|
34
34
|
"@typescript-eslint/parser": "^8.19.1",
|
|
35
35
|
"acquit": "1.3.0",
|
|
@@ -46,14 +46,14 @@
|
|
|
46
46
|
"eslint-plugin-markdown": "^5.1.0",
|
|
47
47
|
"eslint-plugin-mocha-no-only": "1.2.0",
|
|
48
48
|
"express": "^4.19.2",
|
|
49
|
-
"fs-extra": "~11.
|
|
49
|
+
"fs-extra": "~11.3.0",
|
|
50
50
|
"highlight.js": "11.11.1",
|
|
51
51
|
"lodash.isequal": "4.5.0",
|
|
52
52
|
"lodash.isequalwith": "4.4.0",
|
|
53
53
|
"markdownlint-cli2": "^0.17.1",
|
|
54
|
-
"marked": "15.0.
|
|
54
|
+
"marked": "15.0.6",
|
|
55
55
|
"mkdirp": "^3.0.1",
|
|
56
|
-
"mocha": "11.0
|
|
56
|
+
"mocha": "11.1.0",
|
|
57
57
|
"moment": "2.30.1",
|
|
58
58
|
"mongodb-memory-server": "10.1.3",
|
|
59
59
|
"ncp": "^2.0.0",
|
|
@@ -63,8 +63,8 @@
|
|
|
63
63
|
"sinon": "19.0.2",
|
|
64
64
|
"stream-browserify": "3.0.0",
|
|
65
65
|
"tsd": "0.31.2",
|
|
66
|
-
"typescript": "5.7.
|
|
67
|
-
"uuid": "11.0.
|
|
66
|
+
"typescript": "5.7.3",
|
|
67
|
+
"uuid": "11.0.5",
|
|
68
68
|
"webpack": "5.97.1"
|
|
69
69
|
},
|
|
70
70
|
"directories": {
|
package/types/expressions.d.ts
CHANGED
|
@@ -2301,6 +2301,18 @@ declare module 'mongoose' {
|
|
|
2301
2301
|
}
|
|
2302
2302
|
}
|
|
2303
2303
|
|
|
2304
|
+
export interface Median {
|
|
2305
|
+
/**
|
|
2306
|
+
* Returns an approximation of the median, the 50th percentile, as a scalar value.
|
|
2307
|
+
*
|
|
2308
|
+
* @see https://www.mongodb.com/docs/v7.0/reference/operator/aggregation/median/
|
|
2309
|
+
*/
|
|
2310
|
+
$median: {
|
|
2311
|
+
input: number | Expression,
|
|
2312
|
+
method: 'approximate'
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
|
|
2304
2316
|
export interface StdDevPop {
|
|
2305
2317
|
/**
|
|
2306
2318
|
* Calculates the population standard deviation of the input values. Use if the values encompass the entire
|
|
@@ -2859,6 +2871,7 @@ declare module 'mongoose' {
|
|
|
2859
2871
|
Expression.Locf |
|
|
2860
2872
|
Expression.Max |
|
|
2861
2873
|
Expression.MaxN |
|
|
2874
|
+
Expression.Median |
|
|
2862
2875
|
Expression.Min |
|
|
2863
2876
|
Expression.MinN |
|
|
2864
2877
|
Expression.Push |
|
|
@@ -2891,6 +2904,7 @@ declare module 'mongoose' {
|
|
|
2891
2904
|
Expression.ExpMovingAvg |
|
|
2892
2905
|
Expression.Integral |
|
|
2893
2906
|
Expression.Max |
|
|
2907
|
+
Expression.Median |
|
|
2894
2908
|
Expression.Min |
|
|
2895
2909
|
Expression.StdDevPop |
|
|
2896
2910
|
Expression.StdDevSamp |
|
|
@@ -2963,6 +2977,7 @@ declare module 'mongoose' {
|
|
|
2963
2977
|
Expression.LastN |
|
|
2964
2978
|
Expression.Max |
|
|
2965
2979
|
Expression.MaxN |
|
|
2980
|
+
Expression.Median |
|
|
2966
2981
|
Expression.MergeObjects |
|
|
2967
2982
|
Expression.Min |
|
|
2968
2983
|
Expression.MinN |
|
package/valnotes.md
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
## sift where
|
|
2
|
-
|
|
3
|
-
```
|
|
4
|
-
it('match prevents using $where', async function() {
|
|
5
|
-
const ParentSchema = new Schema({
|
|
6
|
-
name: String,
|
|
7
|
-
child: {
|
|
8
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
9
|
-
ref: 'Child'
|
|
10
|
-
},
|
|
11
|
-
children: [{
|
|
12
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
13
|
-
ref: 'Child'
|
|
14
|
-
}]
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
const ChildSchema = new Schema({
|
|
18
|
-
name: String
|
|
19
|
-
});
|
|
20
|
-
ChildSchema.virtual('parent', {
|
|
21
|
-
ref: 'Parent',
|
|
22
|
-
localField: '_id',
|
|
23
|
-
foreignField: 'parent'
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
const Parent = db.model('Parent', ParentSchema);
|
|
27
|
-
const Child = db.model('Child', ChildSchema);
|
|
28
|
-
|
|
29
|
-
const child = await Child.create({ name: 'Luke' });
|
|
30
|
-
const parent = await Parent.create({ name: 'Anakin', child: child._id });
|
|
31
|
-
|
|
32
|
-
await assert.rejects(
|
|
33
|
-
() => Parent.findOne().populate({ path: 'child', match: () => ({ $where: 'typeof console !== "undefined" ? doesNotExist("foo") : true;' }) }),
|
|
34
|
-
/Cannot use \$where filter with populate\(\) match/
|
|
35
|
-
);
|
|
36
|
-
await assert.rejects(
|
|
37
|
-
() => Parent.find().populate({ path: 'child', match: () => ({ $where: 'typeof console !== "undefined" ? doesNotExist("foo") : true;' }) }),
|
|
38
|
-
/Cannot use \$where filter with populate\(\) match/
|
|
39
|
-
);
|
|
40
|
-
await assert.rejects(
|
|
41
|
-
() => parent.populate({ path: 'child', match: () => ({ $where: 'typeof console !== "undefined" ? doesNotExist("foo") : true;' }) }),
|
|
42
|
-
/Cannot use \$where filter with populate\(\) match/
|
|
43
|
-
);
|
|
44
|
-
await assert.rejects(
|
|
45
|
-
() => Child.find().populate({ path: 'parent', match: () => ({ $where: 'typeof console !== "undefined" ? doesNotExist("foo") : true;' }) }),
|
|
46
|
-
/Cannot use \$where filter with populate\(\) match/
|
|
47
|
-
);
|
|
48
|
-
await assert.rejects(
|
|
49
|
-
() => Child.find().populate({ path: 'parent', match: () => ({ $or: [{ $where: 'typeof console !== "undefined" ? doesNotExist("foo") : true;' }] }) }),
|
|
50
|
-
/Cannot use \$where filter with populate\(\) match/
|
|
51
|
-
);
|
|
52
|
-
await assert.rejects(
|
|
53
|
-
() => Child.find().populate({ path: 'parent', match: () => ({ $and: [{ $where: 'typeof console !== "undefined" ? doesNotExist("foo") : true;' }] }) }),
|
|
54
|
-
/Cannot use \$where filter with populate\(\) match/
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
class MyClass {}
|
|
58
|
-
MyClass.prototype.$where = 'typeof console !== "undefined" ? doesNotExist("foo") : true;';
|
|
59
|
-
// OK because sift only looks through own properties
|
|
60
|
-
await Child.find().populate({ path: 'parent', match: () => new MyClass() });
|
|
61
|
-
});
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
```
|
|
65
|
-
/**
|
|
66
|
-
* Throw an error if there are any $where keys
|
|
67
|
-
*/
|
|
68
|
-
|
|
69
|
-
function throwOn$where(match) {
|
|
70
|
-
if (match == null) {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
if (typeof match !== 'object') {
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
for (const key of Object.keys(match)) {
|
|
77
|
-
if (key === '$where') {
|
|
78
|
-
throw new MongooseError('Cannot use $where filter with populate() match');
|
|
79
|
-
}
|
|
80
|
-
if (match[key] != null && typeof match[key] === 'object') {
|
|
81
|
-
throwOn$where(match[key]);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
```
|