mongoose 7.5.2 → 7.5.4

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.
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const assert = require('assert');
4
+ const { Long } = require('bson');
4
5
 
5
6
  /**
6
7
  * Given a value, cast it to a BigInt, or throw an `Error` if the value
@@ -23,6 +24,10 @@ module.exports = function castBigInt(val) {
23
24
  return val;
24
25
  }
25
26
 
27
+ if (val instanceof Long) {
28
+ return val.toBigInt();
29
+ }
30
+
26
31
  if (typeof val === 'string' || typeof val === 'number') {
27
32
  return BigInt(val);
28
33
  }
package/lib/cast.js CHANGED
@@ -309,8 +309,21 @@ module.exports = function cast(schema, obj, options, context) {
309
309
  while (k--) {
310
310
  $cond = ks[k];
311
311
  nested = val[$cond];
312
-
313
- if ($cond === '$not') {
312
+ if ($cond === '$elemMatch') {
313
+ if (nested && schematype != null && schematype.schema != null) {
314
+ cast(schematype.schema, nested, options, context);
315
+ } else if (nested && schematype != null && schematype.$isMongooseArray) {
316
+ if (utils.isPOJO(nested) && nested.$not != null) {
317
+ cast(schema, nested, options, context);
318
+ } else {
319
+ val[$cond] = schematype.castForQuery(
320
+ $cond,
321
+ nested,
322
+ context
323
+ );
324
+ }
325
+ }
326
+ } else if ($cond === '$not') {
314
327
  if (nested && schematype) {
315
328
  _keys = Object.keys(nested);
316
329
  if (_keys.length && isOperator(_keys[0])) {
@@ -337,6 +350,7 @@ module.exports = function cast(schema, obj, options, context) {
337
350
  context
338
351
  );
339
352
  }
353
+
340
354
  }
341
355
  }
342
356
  } else if (Array.isArray(val) && ['Buffer', 'Array'].indexOf(schematype.instance) === -1) {
@@ -34,7 +34,7 @@ const util = require('util');
34
34
  * @api public
35
35
  */
36
36
 
37
- function QueryCursor(query, options) {
37
+ function QueryCursor(query) {
38
38
  // set autoDestroy=true because on node 12 it's by default false
39
39
  // gh-10902 need autoDestroy to destroy correctly and emit 'close' event
40
40
  Readable.call(this, { autoDestroy: true, objectMode: true });
@@ -46,7 +46,7 @@ function QueryCursor(query, options) {
46
46
  this._mongooseOptions = {};
47
47
  this._transforms = [];
48
48
  this.model = model;
49
- this.options = options || {};
49
+ this.options = {};
50
50
  model.hooks.execPre('find', query, (err) => {
51
51
  if (err != null) {
52
52
  if (err instanceof kareem.skipWrappedFunction) {
@@ -70,20 +70,18 @@ function QueryCursor(query, options) {
70
70
  this.listeners('error').length > 0 && this.emit('error', err);
71
71
  return;
72
72
  }
73
+ Object.assign(this.options, query._optionsForExec());
73
74
  this._transforms = this._transforms.concat(query._transforms.slice());
74
75
  if (this.options.transform) {
75
- this._transforms.push(options.transform);
76
+ this._transforms.push(this.options.transform);
76
77
  }
77
78
  // Re: gh-8039, you need to set the `cursor.batchSize` option, top-level
78
79
  // `batchSize` option doesn't work.
79
80
  if (this.options.batchSize) {
80
- this.options.cursor = options.cursor || {};
81
- this.options.cursor.batchSize = options.batchSize;
82
-
83
81
  // Max out the number of documents we'll populate in parallel at 5000.
84
82
  this.options._populateBatchSize = Math.min(this.options.batchSize, 5000);
85
83
  }
86
- Object.assign(this.options, query._optionsForExec());
84
+
87
85
  if (model.collection._shouldBufferCommands() && model.collection.buffer) {
88
86
  model.collection.queue.push([
89
87
  () => _getRawCursor(query, this)
package/lib/document.js CHANGED
@@ -1060,10 +1060,6 @@ Document.prototype.$set = function $set(path, val, type, options) {
1060
1060
  [path, val] = [val, path];
1061
1061
  }
1062
1062
 
1063
- if ('_id' in path && 'id' in path) {
1064
- delete path.id;
1065
- }
1066
-
1067
1063
  prefix = val ? val + '.' : '';
1068
1064
  keys = getKeysInSchemaOrder(this.$__schema, path);
1069
1065
 
@@ -1670,7 +1666,11 @@ Document.prototype.$__set = function(pathToMark, path, options, constructing, pa
1670
1666
  val[arrayAtomicsSymbol] = priorVal[arrayAtomicsSymbol];
1671
1667
  val[arrayAtomicsBackupSymbol] = priorVal[arrayAtomicsBackupSymbol];
1672
1668
  if (utils.isMongooseDocumentArray(val)) {
1673
- val.forEach(doc => { doc.isNew = false; });
1669
+ val.forEach(doc => {
1670
+ if (doc != null) {
1671
+ doc.$isNew = false;
1672
+ }
1673
+ });
1674
1674
  }
1675
1675
  }
1676
1676
 
@@ -1690,6 +1690,13 @@ Document.prototype.$__set = function(pathToMark, path, options, constructing, pa
1690
1690
  if (last) {
1691
1691
  if (obj instanceof Map) {
1692
1692
  obj.set(parts[i], val);
1693
+ } else if (obj.$isSingleNested) {
1694
+ if (!(parts[i] in obj)) {
1695
+ obj[parts[i]] = val;
1696
+ obj._doc[parts[i]] = val;
1697
+ } else {
1698
+ obj._doc[parts[i]] = val;
1699
+ }
1693
1700
  } else {
1694
1701
  obj[parts[i]] = val;
1695
1702
  }
@@ -1701,7 +1708,7 @@ Document.prototype.$__set = function(pathToMark, path, options, constructing, pa
1701
1708
  } else if (value && value instanceof Embedded) {
1702
1709
  obj = value;
1703
1710
  } else if (value && !Array.isArray(value) && value.$isSingleNested) {
1704
- obj = value._doc;
1711
+ obj = value;
1705
1712
  } else if (value && Array.isArray(value)) {
1706
1713
  obj = value;
1707
1714
  } else if (value == null) {
@@ -2646,7 +2653,7 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip) {
2646
2653
  const modifiedPaths = doc.modifiedPaths();
2647
2654
  for (const subdoc of subdocs) {
2648
2655
  if (subdoc.$basePath) {
2649
- const fullPathToSubdoc = subdoc.$__fullPathWithIndexes();
2656
+ const fullPathToSubdoc = subdoc.$isSingleNested ? subdoc.$__pathRelativeToParent() : subdoc.$__fullPathWithIndexes();
2650
2657
 
2651
2658
  // Remove child paths for now, because we'll be validating the whole
2652
2659
  // subdoc.
@@ -349,7 +349,7 @@ function _setClient(conn, client, options, dbName) {
349
349
  client.s.options.hosts &&
350
350
  client.s.options.hosts[0] &&
351
351
  client.s.options.hosts[0].port || void 0;
352
- conn.name = dbName != null ? dbName : client && client.s && client.s.options && client.s.options.dbName || void 0;
352
+ conn.name = dbName != null ? dbName : db.databaseName;
353
353
  conn._closeCalled = client._closeCalled;
354
354
 
355
355
  const _handleReconnect = () => {
@@ -7,15 +7,18 @@ const getDiscriminatorByValue = require('./getDiscriminatorByValue');
7
7
  * @api private
8
8
  */
9
9
 
10
- module.exports = function getConstructor(Constructor, value) {
10
+ module.exports = function getConstructor(Constructor, value, defaultDiscriminatorValue) {
11
11
  const discriminatorKey = Constructor.schema.options.discriminatorKey;
12
- if (value != null &&
13
- Constructor.discriminators &&
14
- value[discriminatorKey] != null) {
15
- if (Constructor.discriminators[value[discriminatorKey]]) {
16
- Constructor = Constructor.discriminators[value[discriminatorKey]];
12
+ let discriminatorValue = (value != null && value[discriminatorKey]);
13
+ if (discriminatorValue == null) {
14
+ discriminatorValue = defaultDiscriminatorValue;
15
+ }
16
+ if (Constructor.discriminators &&
17
+ discriminatorValue != null) {
18
+ if (Constructor.discriminators[discriminatorValue]) {
19
+ Constructor = Constructor.discriminators[discriminatorValue];
17
20
  } else {
18
- const constructorByValue = getDiscriminatorByValue(Constructor.discriminators, value[discriminatorKey]);
21
+ const constructorByValue = getDiscriminatorByValue(Constructor.discriminators, discriminatorValue);
19
22
  if (constructorByValue) {
20
23
  Constructor = constructorByValue;
21
24
  }
@@ -20,6 +20,8 @@ const setDefaultsOnInsert = require('../setDefaultsOnInsert');
20
20
 
21
21
  module.exports = function castBulkWrite(originalModel, op, options) {
22
22
  const now = originalModel.base.now();
23
+
24
+ const globalSetDefaultsOnInsert = originalModel.base.options.setDefaultsOnInsert;
23
25
  if (op['insertOne']) {
24
26
  return (callback) => {
25
27
  const model = decideModelByObject(originalModel, op['insertOne']['document']);
@@ -69,7 +71,10 @@ module.exports = function castBulkWrite(originalModel, op, options) {
69
71
  applyTimestampsToChildren(now, op['updateOne']['update'], model.schema);
70
72
  }
71
73
 
72
- if (op['updateOne'].setDefaultsOnInsert !== false) {
74
+ const shouldSetDefaultsOnInsert = op['updateOne'].setDefaultsOnInsert == null ?
75
+ globalSetDefaultsOnInsert :
76
+ op['updateOne'].setDefaultsOnInsert;
77
+ if (shouldSetDefaultsOnInsert !== false) {
73
78
  setDefaultsOnInsert(op['updateOne']['filter'], model.schema, op['updateOne']['update'], {
74
79
  setDefaultsOnInsert: true,
75
80
  upsert: op['updateOne'].upsert
@@ -106,7 +111,11 @@ module.exports = function castBulkWrite(originalModel, op, options) {
106
111
  const schema = model.schema;
107
112
  const strict = options.strict != null ? options.strict : model.schema.options.strict;
108
113
 
109
- if (op['updateMany'].setDefaultsOnInsert !== false) {
114
+ const shouldSetDefaultsOnInsert = op['updateMany'].setDefaultsOnInsert == null ?
115
+ globalSetDefaultsOnInsert :
116
+ op['updateMany'].setDefaultsOnInsert;
117
+
118
+ if (shouldSetDefaultsOnInsert !== false) {
110
119
  setDefaultsOnInsert(op['updateMany']['filter'], model.schema, op['updateMany']['update'], {
111
120
  setDefaultsOnInsert: true,
112
121
  upsert: op['updateMany'].upsert
@@ -29,7 +29,6 @@ const arithmeticOperatorNumber = new Set([
29
29
  '$floor',
30
30
  '$ln',
31
31
  '$log10',
32
- '$round',
33
32
  '$sqrt',
34
33
  '$sin',
35
34
  '$cos',
@@ -118,6 +117,13 @@ function _castExpression(val, schema, strictQuery) {
118
117
  if (val.$size) {
119
118
  val.$size = castNumberOperator(val.$size, schema, strictQuery);
120
119
  }
120
+ if (val.$round) {
121
+ const $round = val.$round;
122
+ if (!Array.isArray($round) || $round.length < 1 || $round.length > 2) {
123
+ throw new CastError('Array', $round, '$round');
124
+ }
125
+ val.$round = $round.map(v => castNumberOperator(v, schema, strictQuery));
126
+ }
121
127
 
122
128
  _omitUndefined(val);
123
129
 
package/lib/index.js CHANGED
@@ -694,7 +694,9 @@ Mongoose.prototype._applyPlugins = function(schema, options) {
694
694
 
695
695
  options = options || {};
696
696
  options.applyPluginsToDiscriminators = _mongoose.options && _mongoose.options.applyPluginsToDiscriminators || false;
697
- options.applyPluginsToChildSchemas = typeof (_mongoose.options && _mongoose.options.applyPluginsToDiscriminators) === 'boolean' ? _mongoose.options.applyPluginsToDiscriminators : true;
697
+ options.applyPluginsToChildSchemas = typeof (_mongoose.options && _mongoose.options.applyPluginsToChildSchemas) === 'boolean' ?
698
+ _mongoose.options.applyPluginsToChildSchemas :
699
+ true;
698
700
  applyPlugins(schema, _mongoose.plugins, options, '$globalPluginsApplied');
699
701
  };
700
702
 
package/lib/model.js CHANGED
@@ -3565,11 +3565,9 @@ Model.bulkWrite = async function bulkWrite(ops, options) {
3565
3565
  * @param {Boolean} [options.j=true] If false, disable [journal acknowledgement](https://www.mongodb.com/docs/manual/reference/write-concern/#j-option)
3566
3566
  *
3567
3567
  */
3568
- Model.bulkSave = async function(documents, options) {
3568
+ Model.bulkSave = async function bulkSave(documents, options) {
3569
3569
  options = options || {};
3570
3570
 
3571
- const writeOperations = this.buildBulkWriteOperations(documents, { skipValidation: true, timestamps: options.timestamps });
3572
-
3573
3571
  if (options.timestamps != null) {
3574
3572
  for (const document of documents) {
3575
3573
  document.$__.saveOptions = document.$__.saveOptions || {};
@@ -3586,6 +3584,8 @@ Model.bulkSave = async function(documents, options) {
3586
3584
 
3587
3585
  await Promise.all(documents.map(buildPreSavePromise));
3588
3586
 
3587
+ const writeOperations = this.buildBulkWriteOperations(documents, { skipValidation: true, timestamps: options.timestamps });
3588
+
3589
3589
  const { bulkWriteResult, bulkWriteError } = await this.bulkWrite(writeOperations, options).then(
3590
3590
  (res) => ({ bulkWriteResult: res, bulkWriteError: null }),
3591
3591
  (err) => ({ bulkWriteResult: null, bulkWriteError: err })
package/lib/query.js CHANGED
@@ -5043,15 +5043,13 @@ Query.prototype.cursor = function cursor(opts) {
5043
5043
  this.setOptions(opts);
5044
5044
  }
5045
5045
 
5046
- const options = this._optionsForExec();
5047
-
5048
5046
  try {
5049
5047
  this.cast(this.model);
5050
5048
  } catch (err) {
5051
- return (new QueryCursor(this, options))._markError(err);
5049
+ return (new QueryCursor(this))._markError(err);
5052
5050
  }
5053
5051
 
5054
- return new QueryCursor(this, options);
5052
+ return new QueryCursor(this);
5055
5053
  };
5056
5054
 
5057
5055
  // the rest of these are basically to support older Mongoose syntax with mquery
@@ -199,6 +199,7 @@ exports.applyPaths = function applyPaths(fields, schema) {
199
199
  // projection if `name` has schema-level `select: true`.
200
200
  if ((!type || !type.selected) || exclude !== false) {
201
201
  fields[path] = 0;
202
+ exclude = true;
202
203
  } else if (type && type.selected && exclude === false) {
203
204
  // Make a note of minus paths that are overwriting paths that are
204
205
  // included by default.
@@ -161,7 +161,9 @@ SubdocumentPath.prototype.cast = function(val, doc, init, priorVal, options) {
161
161
  throw new ObjectExpectedError(this.path, val);
162
162
  }
163
163
 
164
- const Constructor = getConstructor(this.caster, val);
164
+ const discriminatorKeyPath = this.schema.path(this.schema.options.discriminatorKey);
165
+ const defaultDiscriminatorValue = discriminatorKeyPath == null ? null : discriminatorKeyPath.getDefault(doc);
166
+ const Constructor = getConstructor(this.caster, val, defaultDiscriminatorValue);
165
167
 
166
168
  let subdoc;
167
169
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "7.5.2",
4
+ "version": "7.5.4",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -28,9 +28,9 @@
28
28
  "sift": "16.0.1"
29
29
  },
30
30
  "devDependencies": {
31
- "@babel/core": "7.22.11",
32
- "@babel/preset-env": "7.22.14",
33
- "@typescript-eslint/eslint-plugin": "5.61.0",
31
+ "@babel/core": "7.23.0",
32
+ "@babel/preset-env": "7.22.20",
33
+ "@typescript-eslint/eslint-plugin": "5.62.0",
34
34
  "@typescript-eslint/parser": "5.62.0",
35
35
  "acquit": "1.3.0",
36
36
  "acquit-ignore": "0.2.1",
@@ -46,7 +46,7 @@
46
46
  "crypto-browserify": "3.12.0",
47
47
  "dotenv": "16.3.1",
48
48
  "dox": "1.0.0",
49
- "eslint": "8.48.0",
49
+ "eslint": "8.50.0",
50
50
  "eslint-plugin-markdown": "^3.0.0",
51
51
  "eslint-plugin-mocha-no-only": "1.1.1",
52
52
  "express": "^4.18.1",
@@ -54,7 +54,7 @@
54
54
  "highlight.js": "11.8.0",
55
55
  "lodash.isequal": "4.5.0",
56
56
  "lodash.isequalwith": "4.4.0",
57
- "markdownlint-cli2": "^0.9.2",
57
+ "markdownlint-cli2": "^0.10.0",
58
58
  "marked": "4.3.0",
59
59
  "mkdirp": "^3.0.1",
60
60
  "mocha": "10.2.0",
@@ -64,11 +64,11 @@
64
64
  "nyc": "15.1.0",
65
65
  "pug": "3.0.2",
66
66
  "q": "1.5.1",
67
- "sinon": "15.2.0",
67
+ "sinon": "16.0.0",
68
68
  "stream-browserify": "3.0.0",
69
69
  "tsd": "0.29.0",
70
70
  "typescript": "5.2.2",
71
- "uuid": "9.0.0",
71
+ "uuid": "9.0.1",
72
72
  "webpack": "5.88.2"
73
73
  },
74
74
  "directories": {
@@ -132,6 +132,7 @@ async function run() {
132
132
  await Content.init();
133
133
 
134
134
  await Content.deleteMany({ version });
135
+ let count = 0;
135
136
  for (const content of contents) {
136
137
  if (version === '7.x') {
137
138
  let url = content.url.startsWith('/') ? content.url : `/${content.url}`;
@@ -143,6 +144,7 @@ async function run() {
143
144
  const url = content.url.startsWith('/') ? content.url : `/${content.url}`;
144
145
  content.url = `/docs/${version}/docs${url}`;
145
146
  }
147
+ console.log(`${++count} / ${contents.length}`);
146
148
  await content.save();
147
149
  }
148
150
 
package/types/index.d.ts CHANGED
@@ -230,13 +230,13 @@ declare module 'mongoose' {
230
230
  ObtainDocumentType<any, EnforcedDocType, ResolveSchemaOptions<TSchemaOptions>>,
231
231
  ResolveSchemaOptions<TSchemaOptions>
232
232
  >,
233
- THydratedDocumentType = HydratedDocument<DocType, TVirtuals & TInstanceMethods>
233
+ THydratedDocumentType = HydratedDocument<FlatRecord<DocType>, TVirtuals & TInstanceMethods>
234
234
  >
235
235
  extends events.EventEmitter {
236
236
  /**
237
237
  * Create a new schema
238
238
  */
239
- constructor(definition?: SchemaDefinition<SchemaDefinitionType<EnforcedDocType>, EnforcedDocType> | DocType, options?: SchemaOptions<DocType, TInstanceMethods, TQueryHelpers, TStaticMethods, TVirtuals, THydratedDocumentType> | ResolveSchemaOptions<TSchemaOptions>);
239
+ constructor(definition?: SchemaDefinition<SchemaDefinitionType<EnforcedDocType>, EnforcedDocType> | DocType, options?: SchemaOptions<FlatRecord<DocType>, TInstanceMethods, TQueryHelpers, TStaticMethods, TVirtuals, THydratedDocumentType> | ResolveSchemaOptions<TSchemaOptions>);
240
240
 
241
241
  /** Adds key path / schema type pairs to this schema. */
242
242
  add(obj: SchemaDefinition<SchemaDefinitionType<EnforcedDocType>> | Schema, prefix?: string): this;
package/types/models.d.ts CHANGED
@@ -400,6 +400,10 @@ declare module 'mongoose' {
400
400
  doc: DocContents,
401
401
  options: InsertManyOptions
402
402
  ): Promise<Array<MergeType<THydratedDocumentType, Omit<DocContents, '_id'>>>>;
403
+ insertMany<DocContents = TRawDocType>(
404
+ docs: Array<DocContents | TRawDocType>,
405
+ options: InsertManyOptions
406
+ ): Promise<Array<MergeType<THydratedDocumentType, Omit<DocContents, '_id'>>>>;
403
407
  insertMany<DocContents = TRawDocType>(
404
408
  doc: DocContents
405
409
  ): Promise<