mongoose 9.0.2 → 9.1.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.
Files changed (88) hide show
  1. package/lib/aggregate.js +1 -1
  2. package/lib/cast/string.js +1 -1
  3. package/lib/cast.js +7 -15
  4. package/lib/collection.js +2 -2
  5. package/lib/connection.js +20 -14
  6. package/lib/cursor/changeStream.js +5 -5
  7. package/lib/document.js +117 -77
  8. package/lib/drivers/node-mongodb-native/collection.js +5 -17
  9. package/lib/drivers/node-mongodb-native/connection.js +8 -23
  10. package/lib/error/cast.js +1 -1
  11. package/lib/helpers/aggregate/prepareDiscriminatorPipeline.js +4 -4
  12. package/lib/helpers/clone.js +8 -8
  13. package/lib/helpers/common.js +4 -4
  14. package/lib/helpers/cursor/eachAsync.js +1 -1
  15. package/lib/helpers/discriminator/getConstructor.js +1 -1
  16. package/lib/helpers/discriminator/getSchemaDiscriminatorByValue.js +1 -1
  17. package/lib/helpers/discriminator/mergeDiscriminatorSchema.js +2 -2
  18. package/lib/helpers/document/applyDefaults.js +1 -1
  19. package/lib/helpers/document/applyTimestamps.js +2 -1
  20. package/lib/helpers/document/applyVirtuals.js +4 -3
  21. package/lib/helpers/document/cleanModifiedSubpaths.js +1 -1
  22. package/lib/helpers/document/compile.js +4 -4
  23. package/lib/helpers/document/getDeepestSubdocumentForPath.js +1 -1
  24. package/lib/helpers/indexes/decorateDiscriminatorIndexOptions.js +1 -1
  25. package/lib/helpers/indexes/getRelatedIndexes.js +3 -3
  26. package/lib/helpers/model/castBulkWrite.js +5 -9
  27. package/lib/helpers/model/discriminator.js +1 -1
  28. package/lib/helpers/populate/assignRawDocsToIdStructure.js +1 -1
  29. package/lib/helpers/populate/assignVals.js +4 -4
  30. package/lib/helpers/populate/getModelsMapForPopulate.js +25 -23
  31. package/lib/helpers/populate/getSchemaTypes.js +6 -7
  32. package/lib/helpers/printJestWarning.js +1 -1
  33. package/lib/helpers/processConnectionOptions.js +1 -1
  34. package/lib/helpers/query/castUpdate.js +12 -12
  35. package/lib/helpers/query/getEmbeddedDiscriminatorPath.js +2 -2
  36. package/lib/helpers/query/handleImmutable.js +2 -2
  37. package/lib/helpers/query/sanitizeFilter.js +1 -1
  38. package/lib/helpers/schema/applyPlugins.js +1 -1
  39. package/lib/helpers/schema/applyReadConcern.js +1 -1
  40. package/lib/helpers/schema/applyWriteConcern.js +4 -2
  41. package/lib/helpers/schema/getIndexes.js +3 -3
  42. package/lib/helpers/schema/getSubdocumentStrictValue.js +1 -1
  43. package/lib/helpers/schema/handleIdOption.js +1 -1
  44. package/lib/helpers/schema/idGetter.js +1 -1
  45. package/lib/helpers/schematype/handleImmutable.js +1 -1
  46. package/lib/helpers/setDefaultsOnInsert.js +2 -5
  47. package/lib/helpers/timestamps/setDocumentTimestamps.js +2 -2
  48. package/lib/helpers/timestamps/setupTimestamps.js +2 -2
  49. package/lib/helpers/update/applyTimestampsToUpdate.js +10 -9
  50. package/lib/helpers/update/castArrayFilters.js +4 -4
  51. package/lib/helpers/update/decorateUpdateWithVersionKey.js +1 -1
  52. package/lib/helpers/updateValidators.js +4 -4
  53. package/lib/model.js +33 -44
  54. package/lib/mongoose.js +5 -5
  55. package/lib/options/virtualOptions.js +1 -1
  56. package/lib/plugins/saveSubdocs.js +2 -2
  57. package/lib/plugins/trackTransaction.js +3 -4
  58. package/lib/query.js +62 -59
  59. package/lib/queryHelpers.js +9 -12
  60. package/lib/schema/array.js +10 -12
  61. package/lib/schema/buffer.js +6 -6
  62. package/lib/schema/documentArray.js +15 -23
  63. package/lib/schema/documentArrayElement.js +3 -3
  64. package/lib/schema/map.js +1 -1
  65. package/lib/schema/mixed.js +2 -2
  66. package/lib/schema/number.js +22 -4
  67. package/lib/schema/objectId.js +1 -1
  68. package/lib/schema/operators/exists.js +1 -1
  69. package/lib/schema/operators/geospatial.js +1 -1
  70. package/lib/schema/string.js +2 -2
  71. package/lib/schema/subdocument.js +9 -12
  72. package/lib/schema/union.js +1 -1
  73. package/lib/schema.js +27 -28
  74. package/lib/schemaType.js +11 -11
  75. package/lib/types/array/index.js +2 -2
  76. package/lib/types/array/methods/index.js +38 -8
  77. package/lib/types/arraySubdocument.js +12 -2
  78. package/lib/types/buffer.js +1 -1
  79. package/lib/types/documentArray/index.js +2 -2
  80. package/lib/types/documentArray/methods/index.js +5 -5
  81. package/lib/types/map.js +8 -8
  82. package/lib/types/subdocument.js +15 -5
  83. package/lib/utils.js +23 -7
  84. package/package.json +2 -2
  85. package/types/index.d.ts +15 -5
  86. package/types/middlewares.d.ts +11 -0
  87. package/types/models.d.ts +15 -5
  88. package/types/schemaoptions.d.ts +4 -2
package/lib/aggregate.js CHANGED
@@ -1049,7 +1049,7 @@ Aggregate.prototype.exec = async function exec() {
1049
1049
 
1050
1050
  this._optionsForExec();
1051
1051
 
1052
- if (this.options && this.options.cursor) {
1052
+ if (this.options?.cursor) {
1053
1053
  return new AggregationCursor(this);
1054
1054
  }
1055
1055
 
@@ -20,7 +20,7 @@ module.exports = function castString(value, path) {
20
20
  }
21
21
 
22
22
  // handle documents being passed
23
- if (value._id && typeof value._id === 'string') {
23
+ if (typeof value?._id === 'string') {
24
24
  return value._id;
25
25
  }
26
26
 
package/lib/cast.js CHANGED
@@ -42,7 +42,7 @@ module.exports = function cast(schema, obj, options, context) {
42
42
  return obj;
43
43
  }
44
44
 
45
- if (schema != null && schema.discriminators != null && obj[schema.options.discriminatorKey] != null) {
45
+ if (schema?.discriminators != null && obj[schema.options.discriminatorKey] != null) {
46
46
  schema = getSchemaDiscriminatorByValue(schema, obj[schema.options.discriminatorKey]) || schema;
47
47
  }
48
48
 
@@ -79,7 +79,7 @@ module.exports = function cast(schema, obj, options, context) {
79
79
  val[k] = cast(discriminatorSchema ? discriminatorSchema : schema, val[k], options, context);
80
80
  }
81
81
 
82
- if (Object.keys(val[k]).length === 0 && beforeCastKeysLength !== 0) {
82
+ if (utils.hasOwnKeys(val[k]) === false && beforeCastKeysLength !== 0) {
83
83
  val.splice(k, 1);
84
84
  }
85
85
  }
@@ -126,16 +126,12 @@ module.exports = function cast(schema, obj, options, context) {
126
126
  const pathFirstHalf = split.slice(0, j).join('.');
127
127
  const pathLastHalf = split.slice(j).join('.');
128
128
  const _schematype = schema.path(pathFirstHalf);
129
- const discriminatorKey = _schematype &&
130
- _schematype.schema &&
131
- _schematype.schema.options &&
132
- _schematype.schema.options.discriminatorKey;
129
+ const discriminatorKey = _schematype?.schema?.options?.discriminatorKey;
133
130
 
134
131
  // gh-6027: if we haven't found the schematype but this path is
135
132
  // underneath an embedded discriminator and the embedded discriminator
136
133
  // key is in the query, use the embedded discriminator schema
137
- if (_schematype != null &&
138
- (_schematype.schema && _schematype.schema.discriminators) != null &&
134
+ if (_schematype?.schema?.discriminators != null &&
139
135
  discriminatorKey != null &&
140
136
  pathLastHalf !== discriminatorKey) {
141
137
  const discriminatorVal = get(obj, pathFirstHalf + '.' + discriminatorKey);
@@ -330,9 +326,9 @@ module.exports = function cast(schema, obj, options, context) {
330
326
  $cond = ks[k];
331
327
  nested = val[$cond];
332
328
  if ($cond === '$elemMatch') {
333
- if (nested && schematype != null && schematype.schema != null) {
329
+ if (nested && schematype?.schema != null) {
334
330
  cast(schematype.schema, nested, options, context);
335
- } else if (nested && schematype != null && schematype.$isMongooseArray) {
331
+ } else if (nested && schematype?.$isMongooseArray) {
336
332
  if (utils.isPOJO(nested) && nested.$not != null) {
337
333
  cast(schema, nested, options, context);
338
334
  } else {
@@ -430,11 +426,7 @@ function getStrictQuery(queryOptions, schemaUserProvidedOptions, schemaOptions,
430
426
  if ('strictQuery' in schemaUserProvidedOptions) {
431
427
  return schemaUserProvidedOptions.strictQuery;
432
428
  }
433
- const mongooseOptions = context &&
434
- context.mongooseCollection &&
435
- context.mongooseCollection.conn &&
436
- context.mongooseCollection.conn.base &&
437
- context.mongooseCollection.conn.base.options;
429
+ const mongooseOptions = context?.mongooseCollection?.conn?.base?.options;
438
430
  if (mongooseOptions) {
439
431
  if ('strictQuery' in mongooseOptions) {
440
432
  return mongooseOptions.strictQuery;
package/lib/collection.js CHANGED
@@ -290,7 +290,7 @@ Collection.prototype._shouldBufferCommands = function _shouldBufferCommands() {
290
290
  if (opts.bufferCommands != null) {
291
291
  return opts.bufferCommands;
292
292
  }
293
- if (opts && opts.schemaUserProvidedOptions != null && opts.schemaUserProvidedOptions.bufferCommands != null) {
293
+ if (opts?.schemaUserProvidedOptions?.bufferCommands != null) {
294
294
  return opts.schemaUserProvidedOptions.bufferCommands;
295
295
  }
296
296
 
@@ -308,7 +308,7 @@ Collection.prototype._getBufferTimeoutMS = function _getBufferTimeoutMS() {
308
308
  if (opts.bufferTimeoutMS != null) {
309
309
  return opts.bufferTimeoutMS;
310
310
  }
311
- if (opts && opts.schemaUserProvidedOptions != null && opts.schemaUserProvidedOptions.bufferTimeoutMS != null) {
311
+ if (opts?.schemaUserProvidedOptions?.bufferTimeoutMS != null) {
312
312
  return opts.schemaUserProvidedOptions.bufferTimeoutMS;
313
313
  }
314
314
  return conn._getBufferTimeoutMS();
package/lib/connection.js CHANGED
@@ -630,7 +630,7 @@ Connection.prototype.createCollections = async function createCollections(option
630
630
  }
631
631
  }
632
632
 
633
- if (!continueOnError && Object.keys(errorsMap).length) {
633
+ if (!continueOnError && utils.hasOwnKeys(errorsMap)) {
634
634
  const message = Object.entries(errorsMap).map(([modelName, err]) => `${modelName}: ${err.message}`).join(', ');
635
635
  const createCollectionsError = new CreateCollectionsError(message, errorsMap);
636
636
  throw createCollectionsError;
@@ -883,7 +883,7 @@ Connection.prototype._getBufferTimeoutMS = function _getBufferTimeoutMS() {
883
883
  if (this.config.bufferTimeoutMS != null) {
884
884
  return this.config.bufferTimeoutMS;
885
885
  }
886
- if (this.base != null && this.base.get('bufferTimeoutMS') != null) {
886
+ if (this.base?.get('bufferTimeoutMS') != null) {
887
887
  return this.base.get('bufferTimeoutMS');
888
888
  }
889
889
  return 10000;
@@ -1250,8 +1250,11 @@ Connection.prototype._close = async function _close(force, destroy) {
1250
1250
  const conn = this;
1251
1251
  switch (this.readyState) {
1252
1252
  case STATES.disconnected:
1253
- if (destroy && this.base.connections.indexOf(conn) !== -1) {
1254
- this.base.connections.splice(this.base.connections.indexOf(conn), 1);
1253
+ if (destroy) {
1254
+ const index = this.base.connections.indexOf(conn);
1255
+ if (index !== -1) {
1256
+ this.base.connections.splice(index, 1);
1257
+ }
1255
1258
  }
1256
1259
  if (!closeCalled) {
1257
1260
  await this.doClose(force);
@@ -1262,8 +1265,11 @@ Connection.prototype._close = async function _close(force, destroy) {
1262
1265
  case STATES.connected:
1263
1266
  this.readyState = STATES.disconnecting;
1264
1267
  await this.doClose(force);
1265
- if (destroy && _this.base.connections.indexOf(conn) !== -1) {
1266
- this.base.connections.splice(this.base.connections.indexOf(conn), 1);
1268
+ if (destroy) {
1269
+ const index = _this.base.connections.indexOf(conn);
1270
+ if (index !== -1) {
1271
+ this.base.connections.splice(index, 1);
1272
+ }
1267
1273
  }
1268
1274
  this.onClose(force);
1269
1275
 
@@ -1349,13 +1355,13 @@ Connection.prototype.onClose = function onClose(force) {
1349
1355
 
1350
1356
  Connection.prototype.collection = function(name, options) {
1351
1357
  const defaultOptions = {
1352
- autoIndex: this.config.autoIndex != null ? this.config.autoIndex : this.base.options.autoIndex,
1353
- autoCreate: this.config.autoCreate != null ? this.config.autoCreate : this.base.options.autoCreate,
1354
- autoSearchIndex: this.config.autoSearchIndex != null ? this.config.autoSearchIndex : this.base.options.autoSearchIndex
1358
+ autoIndex: this.config.autoIndex ?? this.base.options.autoIndex,
1359
+ autoCreate: this.config.autoCreate ?? this.base.options.autoCreate,
1360
+ autoSearchIndex: this.config.autoSearchIndex ?? this.base.options.autoSearchIndex
1355
1361
  };
1356
1362
  options = Object.assign({}, defaultOptions, options ? clone(options) : {});
1357
1363
  options.$wasForceClosed = this.$wasForceClosed;
1358
- const Collection = this.base && this.base.__driver && this.base.__driver.Collection || driver.get().Collection;
1364
+ const Collection = this.base?.__driver?.Collection || driver.get().Collection;
1359
1365
  if (!(name in this.collections)) {
1360
1366
  this.collections[name] = new Collection(name, this, options);
1361
1367
  }
@@ -1456,7 +1462,7 @@ Connection.prototype.model = function model(name, schema, collection, options) {
1456
1462
  const opts = Object.assign(defaultOptions, options, { connection: this });
1457
1463
  if (this.models[name] && !collection && opts.overwriteModels !== true) {
1458
1464
  // model exists but we are not subclassing with custom collection
1459
- if (schema && schema.instanceOfSchema && schema !== this.models[name].schema) {
1465
+ if (schema?.instanceOfSchema && schema !== this.models[name].schema) {
1460
1466
  throw new MongooseError.OverwriteModelError(name);
1461
1467
  }
1462
1468
  return this.models[name];
@@ -1464,7 +1470,7 @@ Connection.prototype.model = function model(name, schema, collection, options) {
1464
1470
 
1465
1471
  let model;
1466
1472
 
1467
- if (schema && schema.instanceOfSchema) {
1473
+ if (schema?.instanceOfSchema) {
1468
1474
  applyPlugins(schema, this.plugins, null, '$connectionPluginsApplied');
1469
1475
 
1470
1476
  // compile a model
@@ -1672,7 +1678,7 @@ Connection.prototype.shouldAuthenticate = function shouldAuthenticate() {
1672
1678
  * a password, otherwise false.
1673
1679
  */
1674
1680
  Connection.prototype.authMechanismDoesNotRequirePassword = function authMechanismDoesNotRequirePassword() {
1675
- if (this.options && this.options.auth) {
1681
+ if (this.options?.auth) {
1676
1682
  return noPasswordAuthMechanisms.indexOf(this.options.auth.authMechanism) >= 0;
1677
1683
  }
1678
1684
  return true;
@@ -1772,7 +1778,7 @@ Connection.prototype.syncIndexes = async function syncIndexes(options = {}) {
1772
1778
  }
1773
1779
  }
1774
1780
 
1775
- if (!continueOnError && Object.keys(errorsMap).length) {
1781
+ if (!continueOnError && utils.hasOwnKeys(errorsMap)) {
1776
1782
  const message = Object.entries(errorsMap).map(([modelName, err]) => `${modelName}: ${err.message}`).join(', ');
1777
1783
  const syncIndexesError = new SyncIndexesError(message, errorsMap);
1778
1784
  throw syncIndexesError;
@@ -28,7 +28,7 @@ class ChangeStream extends EventEmitter {
28
28
  this.options = options;
29
29
  this.errored = false;
30
30
 
31
- if (options && options.hydrate && !options.model) {
31
+ if (options?.hydrate && !options.model) {
32
32
  throw new Error(
33
33
  'Cannot create change stream with `hydrate: true` ' +
34
34
  'unless calling `Model.watch()`'
@@ -83,7 +83,7 @@ class ChangeStream extends EventEmitter {
83
83
 
84
84
  driverChangeStreamEvents.forEach(ev => {
85
85
  this.driverChangeStream.on(ev, data => {
86
- if (data != null && data.fullDocument != null && this.options && this.options.hydrate) {
86
+ if (data?.fullDocument != null && this.options?.hydrate) {
87
87
  data.fullDocument = this.options.model.hydrate(data.fullDocument);
88
88
  }
89
89
  this.emit(ev, data);
@@ -102,7 +102,7 @@ class ChangeStream extends EventEmitter {
102
102
 
103
103
  driverChangeStreamEvents.forEach(ev => {
104
104
  this.driverChangeStream.on(ev, data => {
105
- if (data != null && data.fullDocument != null && this.options && this.options.hydrate) {
105
+ if (data?.fullDocument != null && this.options?.hydrate) {
106
106
  data.fullDocument = this.options.model.hydrate(data.fullDocument);
107
107
  }
108
108
  this.emit(ev, data);
@@ -121,7 +121,7 @@ class ChangeStream extends EventEmitter {
121
121
  if (this.errored) {
122
122
  throw new MongooseError('Cannot call next() on errored ChangeStream');
123
123
  }
124
- if (this.options && this.options.hydrate) {
124
+ if (this.options?.hydrate) {
125
125
  if (cb != null) {
126
126
  const originalCb = cb;
127
127
  cb = (err, data) => {
@@ -136,7 +136,7 @@ class ChangeStream extends EventEmitter {
136
136
  }
137
137
 
138
138
  let maybePromise = this.driverChangeStream.next(cb);
139
- if (maybePromise && typeof maybePromise.then === 'function') {
139
+ if (typeof maybePromise?.then === 'function') {
140
140
  maybePromise = maybePromise.then(data => {
141
141
  if (data.fullDocument != null) {
142
142
  data.fullDocument = this.options.model.hydrate(data.fullDocument);