mongoose 6.4.7 → 6.5.2

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 (47) hide show
  1. package/lib/connection.js +23 -3
  2. package/lib/cursor/ChangeStream.js +39 -1
  3. package/lib/document.js +129 -154
  4. package/lib/error/index.js +1 -0
  5. package/lib/error/validation.js +9 -0
  6. package/lib/helpers/document/applyDefaults.js +115 -0
  7. package/lib/helpers/document/cleanModifiedSubpaths.js +3 -3
  8. package/lib/helpers/document/compile.js +7 -6
  9. package/lib/helpers/firstKey.js +8 -0
  10. package/lib/helpers/model/applyDefaultsToPOJO.js +52 -0
  11. package/lib/helpers/model/castBulkWrite.js +1 -1
  12. package/lib/helpers/model/pushNestedArrayPaths.js +15 -0
  13. package/lib/helpers/populate/markArraySubdocsPopulated.js +1 -0
  14. package/lib/helpers/projection/hasIncludedChildren.js +1 -0
  15. package/lib/helpers/promiseOrCallback.js +24 -15
  16. package/lib/helpers/update/applyTimestampsToChildren.js +6 -2
  17. package/lib/index.js +2 -1
  18. package/lib/internal.js +3 -1
  19. package/lib/model.js +237 -95
  20. package/lib/options/SchemaArrayOptions.js +19 -0
  21. package/lib/options/SchemaNumberOptions.js +2 -0
  22. package/lib/options/SchemaObjectIdOptions.js +1 -0
  23. package/lib/plugins/trackTransaction.js +2 -2
  24. package/lib/query.js +30 -11
  25. package/lib/schema/SubdocumentPath.js +10 -0
  26. package/lib/schema/array.js +2 -1
  27. package/lib/schema/documentarray.js +14 -1
  28. package/lib/schema/string.js +3 -0
  29. package/lib/schema.js +22 -3
  30. package/lib/schematype.js +5 -1
  31. package/lib/statemachine.js +23 -9
  32. package/lib/types/buffer.js +23 -21
  33. package/lib/types/map.js +2 -0
  34. package/lib/utils.js +8 -0
  35. package/lib/validoptions.js +1 -0
  36. package/package.json +14 -14
  37. package/{build-browser.js → scripts/build-browser.js} +1 -1
  38. package/types/connection.d.ts +7 -1
  39. package/types/document.d.ts +8 -1
  40. package/types/expressions.d.ts +1 -1
  41. package/types/index.d.ts +31 -28
  42. package/types/inferschematype.d.ts +3 -20
  43. package/types/models.d.ts +53 -49
  44. package/types/mongooseoptions.d.ts +6 -0
  45. package/types/schemaoptions.d.ts +15 -4
  46. package/types/utility.d.ts +19 -0
  47. package/types/virtuals.d.ts +14 -0
package/lib/query.js CHANGED
@@ -166,7 +166,7 @@ Query.base = mquery.prototype;
166
166
  *
167
167
  * MongoDB 2.4 deprecated the use of `$within`, replacing it with `$geoWithin`. Mongoose uses `$geoWithin` by default (which is 100% backward compatible with `$within`). If you are running an older version of MongoDB, set this flag to `false` so your `within()` queries continue to work.
168
168
  *
169
- * @see https://docs.mongodb.org/manual/reference/operator/geoWithin/
169
+ * @see geoWithin https://docs.mongodb.org/manual/reference/operator/geoWithin/
170
170
  * @default true
171
171
  * @property use$geoWithin
172
172
  * @memberOf Query
@@ -262,6 +262,7 @@ Query.prototype.toConstructor = function toConstructor() {
262
262
  * Make a copy of this query so you can re-execute it.
263
263
  *
264
264
  * #### Example:
265
+ *
265
266
  * const q = Book.findOne({ title: 'Casino Royale' });
266
267
  * await q.exec();
267
268
  * await q.exec(); // Throws an error because you can't execute a query twice
@@ -1071,7 +1072,7 @@ Query.prototype.projection = function(arg) {
1071
1072
  * @instance
1072
1073
  * @param {Object|String|String[]} arg
1073
1074
  * @return {Query} this
1074
- * @see SchemaType
1075
+ * @see SchemaType /docs/api/schematype
1075
1076
  * @api public
1076
1077
  */
1077
1078
 
@@ -1598,6 +1599,8 @@ Query.prototype.setOptions = function(options, overwrite) {
1598
1599
  throw new Error('Options must be an object, got "' + options + '"');
1599
1600
  }
1600
1601
 
1602
+ options = Object.assign({}, options);
1603
+
1601
1604
  if (Array.isArray(options.populate)) {
1602
1605
  const populate = options.populate;
1603
1606
  delete options.populate;
@@ -1632,6 +1635,9 @@ Query.prototype.setOptions = function(options, overwrite) {
1632
1635
  this._mongooseOptions.defaults = options.defaults;
1633
1636
  // deleting options.defaults will cause 7287 to fail
1634
1637
  }
1638
+ if (options.lean == null && this.schema && 'lean' in this.schema.options) {
1639
+ this._mongooseOptions.lean = this.schema.options.lean;
1640
+ }
1635
1641
 
1636
1642
  if (typeof options.limit === 'string') {
1637
1643
  try {
@@ -2038,6 +2044,9 @@ Query.prototype.set = function(path, val) {
2038
2044
  }
2039
2045
 
2040
2046
  this._update = this._update || {};
2047
+ if (path in this._update) {
2048
+ delete this._update[path];
2049
+ }
2041
2050
  this._update.$set = this._update.$set || {};
2042
2051
  this._update.$set[path] = val;
2043
2052
  return this;
@@ -2097,6 +2106,7 @@ Query.prototype.get = function get(path) {
2097
2106
  * custom errors.
2098
2107
  *
2099
2108
  * #### Example:
2109
+ *
2100
2110
  * const TestSchema = new Schema({ num: Number });
2101
2111
  * const TestModel = db.model('Test', TestSchema);
2102
2112
  * TestModel.find({ num: 'not a number' }).error(new Error('woops')).exec(function(error) {
@@ -3294,6 +3304,7 @@ function prepareDiscriminatorCriteria(query) {
3294
3304
  * - `rawResult`: if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.3/interfaces/ModifyResult.html)
3295
3305
  *
3296
3306
  * #### Callback Signature
3307
+ *
3297
3308
  * function(error, doc) {
3298
3309
  * // error: any errors that occurred
3299
3310
  * // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
@@ -3436,6 +3447,7 @@ Query.prototype._findOneAndUpdate = wrapThunk(function(callback) {
3436
3447
  * - `rawResult`: if true, resolves to the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.3/interfaces/ModifyResult.html)
3437
3448
  *
3438
3449
  * #### Callback Signature
3450
+ *
3439
3451
  * function(error, doc) {
3440
3452
  * // error: any errors that occurred
3441
3453
  * // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
@@ -3523,6 +3535,7 @@ Query.prototype.findOneAndRemove = function(conditions, options, callback) {
3523
3535
  * - `rawResult`: if true, resolves to the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.3/interfaces/ModifyResult.html)
3524
3536
  *
3525
3537
  * #### Callback Signature
3538
+ *
3526
3539
  * function(error, doc) {
3527
3540
  * // error: any errors that occurred
3528
3541
  * // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
@@ -3642,6 +3655,7 @@ Query.prototype._findOneAndDelete = wrapThunk(function(callback) {
3642
3655
  * - `rawResult`: if true, resolves to the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.3/interfaces/ModifyResult.html)
3643
3656
  *
3644
3657
  * #### Callback Signature
3658
+ *
3645
3659
  * function(error, doc) {
3646
3660
  * // error: any errors that occurred
3647
3661
  * // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
@@ -4414,6 +4428,7 @@ Query.prototype.update = function(conditions, doc, options, callback) {
4414
4428
  * and `post('updateMany')` instead.
4415
4429
  *
4416
4430
  * #### Example:
4431
+ *
4417
4432
  * const res = await Person.updateMany({ name: /Stark$/ }, { isDeleted: true });
4418
4433
  * res.n; // Number of documents matched
4419
4434
  * res.nModified; // Number of documents modified
@@ -4479,6 +4494,7 @@ Query.prototype.updateMany = function(conditions, doc, options, callback) {
4479
4494
  * and `post('updateOne')` instead.
4480
4495
  *
4481
4496
  * #### Example:
4497
+ *
4482
4498
  * const res = await Person.updateOne({ name: 'Jean-Luc Picard' }, { ship: 'USS Enterprise' });
4483
4499
  * res.n; // Number of documents matched
4484
4500
  * res.nModified; // Number of documents modified
@@ -4542,6 +4558,7 @@ Query.prototype.updateOne = function(conditions, doc, options, callback) {
4542
4558
  * and `post('replaceOne')` instead.
4543
4559
  *
4544
4560
  * #### Example:
4561
+ *
4545
4562
  * const res = await Person.replaceOne({ _id: 24601 }, { name: 'Jean Valjean' });
4546
4563
  * res.n; // Number of documents matched
4547
4564
  * res.nModified; // Number of documents modified
@@ -5059,7 +5076,7 @@ function castQuery(query) {
5059
5076
  * @param {Object|Function} [options.match=null] Add an additional filter to the populate query. Can be a filter object containing [MongoDB query syntax](https://docs.mongodb.com/manual/tutorial/query-documents/), or a function that returns a filter object.
5060
5077
  * @param {Function} [options.transform=null] Function that Mongoose will call on every populated document that allows you to transform the populated document.
5061
5078
  * @param {Object} [options.options=null] Additional options like `limit` and `lean`.
5062
- * @see population ./populate.html
5079
+ * @see population /docs/populate
5063
5080
  * @see Query#select #query_Query-select
5064
5081
  * @see Model.populate #model_Model-populate
5065
5082
  * @return {Query} this
@@ -5125,6 +5142,7 @@ Query.prototype.populate = function() {
5125
5142
  * Gets a list of paths to be populated by this query
5126
5143
  *
5127
5144
  * #### Example:
5145
+ *
5128
5146
  * bookSchema.pre('findOne', function() {
5129
5147
  * let keys = this.getPopulatedPaths(); // ['author']
5130
5148
  * });
@@ -5132,6 +5150,7 @@ Query.prototype.populate = function() {
5132
5150
  * Book.findOne({}).populate('author');
5133
5151
  *
5134
5152
  * #### Example:
5153
+ *
5135
5154
  * // Deep populate
5136
5155
  * const q = L1.find().populate({
5137
5156
  * path: 'level2',
@@ -5328,7 +5347,7 @@ Query.prototype._applyPaths = function applyPaths() {
5328
5347
  *
5329
5348
  * @return {QueryCursor}
5330
5349
  * @param {Object} [options]
5331
- * @see QueryCursor
5350
+ * @see QueryCursor /docs/api/querycursor
5332
5351
  * @api public
5333
5352
  */
5334
5353
 
@@ -5484,8 +5503,8 @@ Query.prototype.tailable = function(val, opts) {
5484
5503
  * @param {Object} object Must contain a `type` property which is a String and a `coordinates` property which is an Array. See the examples.
5485
5504
  * @return {Query} this
5486
5505
  * @see $geometry https://docs.mongodb.org/manual/reference/operator/geometry/
5487
- * @see https://docs.mongodb.org/manual/release-notes/2.4/#new-geospatial-indexes-with-geojson-and-improved-spherical-geometry
5488
- * @see https://www.mongodb.org/display/DOCS/Geospatial+Indexing
5506
+ * @see Geospatial Support Enhancements https://www.mongodb.com/docs/manual/release-notes/2.4/#geospatial-support-enhancements
5507
+ * @see MongoDB Geospatial Indexing https://www.mongodb.org/display/DOCS/Geospatial+Indexing
5489
5508
  * @api public
5490
5509
  */
5491
5510
 
@@ -5510,7 +5529,7 @@ Query.prototype.tailable = function(val, opts) {
5510
5529
  * @see $near https://docs.mongodb.org/manual/reference/operator/near/
5511
5530
  * @see $nearSphere https://docs.mongodb.org/manual/reference/operator/nearSphere/
5512
5531
  * @see $maxDistance https://docs.mongodb.org/manual/reference/operator/maxDistance/
5513
- * @see https://www.mongodb.org/display/DOCS/Geospatial+Indexing
5532
+ * @see MongoDB Geospatial Indexing https://www.mongodb.org/display/DOCS/Geospatial+Indexing
5514
5533
  * @api public
5515
5534
  */
5516
5535
 
@@ -5646,7 +5665,7 @@ if (Symbol.asyncIterator != null) {
5646
5665
  * @param {Array|Object} [coordinatePairs...]
5647
5666
  * @return {Query} this
5648
5667
  * @see $polygon https://docs.mongodb.org/manual/reference/operator/polygon/
5649
- * @see https://www.mongodb.org/display/DOCS/Geospatial+Indexing
5668
+ * @see MongoDB Geospatial Indexing https://www.mongodb.org/display/DOCS/Geospatial+Indexing
5650
5669
  * @api public
5651
5670
  */
5652
5671
 
@@ -5666,7 +5685,7 @@ if (Symbol.asyncIterator != null) {
5666
5685
  * @instance
5667
5686
  * @see $box https://docs.mongodb.org/manual/reference/operator/box/
5668
5687
  * @see within() Query#within #query_Query-within
5669
- * @see https://www.mongodb.org/display/DOCS/Geospatial+Indexing
5688
+ * @see MongoDB Geospatial Indexing https://www.mongodb.org/display/DOCS/Geospatial+Indexing
5670
5689
  * @param {Object|Array<Number>} val1 Lower Left Coordinates OR a object of lower-left(ll) and upper-right(ur) Coordinates
5671
5690
  * @param {Array<Number>} [val2] Upper Right Coordinates
5672
5691
  * @return {Query} this
@@ -5712,7 +5731,7 @@ Query.prototype.box = function(ll, ur) {
5712
5731
  * @see $center https://docs.mongodb.org/manual/reference/operator/center/
5713
5732
  * @see $centerSphere https://docs.mongodb.org/manual/reference/operator/centerSphere/
5714
5733
  * @see $geoWithin https://docs.mongodb.org/manual/reference/operator/geoWithin/
5715
- * @see https://www.mongodb.org/display/DOCS/Geospatial+Indexing
5734
+ * @see MongoDB Geospatial Indexing https://www.mongodb.org/display/DOCS/Geospatial+Indexing
5716
5735
  * @api public
5717
5736
  */
5718
5737
 
@@ -5744,7 +5763,7 @@ Query.prototype.center = Query.base.circle;
5744
5763
  * @param {String} [path]
5745
5764
  * @param {Object} val
5746
5765
  * @return {Query} this
5747
- * @see https://www.mongodb.org/display/DOCS/Geospatial+Indexing
5766
+ * @see MongoDB Geospatial Indexing https://www.mongodb.org/display/DOCS/Geospatial+Indexing
5748
5767
  * @see $centerSphere https://docs.mongodb.org/manual/reference/operator/centerSphere/
5749
5768
  * @api public
5750
5769
  */
@@ -47,6 +47,7 @@ function SubdocumentPath(schema, path, options) {
47
47
  this.caster.prototype.$basePath = path;
48
48
  this.schema = schema;
49
49
  this.$isSingleNested = true;
50
+ this.base = schema.base;
50
51
  SchemaType.call(this, path, options, 'Embedded');
51
52
  }
52
53
 
@@ -280,6 +281,7 @@ SubdocumentPath.prototype.doValidateSync = function(value, scope, options) {
280
281
  * Adds a discriminator to this single nested subdocument.
281
282
  *
282
283
  * #### Example:
284
+ *
283
285
  * const shapeSchema = Schema({ name: String }, { discriminatorKey: 'kind' });
284
286
  * const schema = Schema({ shape: shapeSchema });
285
287
  *
@@ -338,6 +340,14 @@ SubdocumentPath.defaultOptions = {};
338
340
 
339
341
  SubdocumentPath.set = SchemaType.set;
340
342
 
343
+ /*!
344
+ * ignore
345
+ */
346
+
347
+ SubdocumentPath.prototype.toJSON = function toJSON() {
348
+ return { path: this.path, options: this.options };
349
+ };
350
+
341
351
  /*!
342
352
  * ignore
343
353
  */
@@ -393,7 +393,8 @@ SchemaArray.prototype.cast = function(value, doc, init, prev, options) {
393
393
  return value;
394
394
  }
395
395
 
396
- if (init || SchemaArray.options.castNonArrays) {
396
+ const castNonArraysOption = this.options.castNonArrays != null ? this.options.castNonArrays : SchemaArray.options.castNonArrays;
397
+ if (init || castNonArraysOption) {
397
398
  // gh-2442: if we're loading this from the db and its not an array, mark
398
399
  // the whole array as modified.
399
400
  if (!!doc && !!init) {
@@ -36,6 +36,13 @@ let Subdocument;
36
36
  */
37
37
 
38
38
  function DocumentArrayPath(key, schema, options, schemaOptions) {
39
+ const schemaTypeIdOption = DocumentArrayPath.defaultOptions &&
40
+ DocumentArrayPath.defaultOptions._id;
41
+ if (schemaTypeIdOption != null) {
42
+ schemaOptions = schemaOptions || {};
43
+ schemaOptions._id = schemaTypeIdOption;
44
+ }
45
+
39
46
  if (schemaOptions != null && schemaOptions._id != null) {
40
47
  schema = handleIdOption(schema, schemaOptions);
41
48
  } else if (options != null && options._id != null) {
@@ -140,6 +147,7 @@ function _createConstructor(schema, options, baseClass) {
140
147
  EmbeddedDocument.prototype.constructor = EmbeddedDocument;
141
148
  EmbeddedDocument.$isArraySubdocument = true;
142
149
  EmbeddedDocument.events = new EventEmitter();
150
+ EmbeddedDocument.base = schema.base;
143
151
 
144
152
  // apply methods
145
153
  for (const i in schema.methods) {
@@ -164,6 +172,7 @@ function _createConstructor(schema, options, baseClass) {
164
172
  * Adds a discriminator to this document array.
165
173
  *
166
174
  * #### Example:
175
+ *
167
176
  * const shapeSchema = Schema({ name: String }, { discriminatorKey: 'kind' });
168
177
  * const schema = Schema({ shapes: [shapeSchema] });
169
178
  *
@@ -342,7 +351,7 @@ DocumentArrayPath.prototype.doValidateSync = function(array, scope, options) {
342
351
  * ignore
343
352
  */
344
353
 
345
- DocumentArrayPath.prototype.getDefault = function(scope) {
354
+ DocumentArrayPath.prototype.getDefault = function(scope, init, options) {
346
355
  let ret = typeof this.defaultValue === 'function'
347
356
  ? this.defaultValue.call(scope)
348
357
  : this.defaultValue;
@@ -351,6 +360,10 @@ DocumentArrayPath.prototype.getDefault = function(scope) {
351
360
  return ret;
352
361
  }
353
362
 
363
+ if (options && options.skipCast) {
364
+ return ret;
365
+ }
366
+
354
367
  // lazy load
355
368
  MongooseDocumentArray || (MongooseDocumentArray = require('../types/DocumentArray'));
356
369
 
@@ -267,6 +267,7 @@ SchemaString.prototype.enum = function() {
267
267
  * Note that `lowercase` does **not** affect regular expression queries:
268
268
  *
269
269
  * #### Example:
270
+ *
270
271
  * // Still queries for documents whose `email` matches the regular
271
272
  * // expression /SomeEmail/. Mongoose does **not** convert the RegExp
272
273
  * // to lowercase.
@@ -305,6 +306,7 @@ SchemaString.prototype.lowercase = function(shouldApply) {
305
306
  * Note that `uppercase` does **not** affect regular expression queries:
306
307
  *
307
308
  * #### Example:
309
+ *
308
310
  * // Mongoose does **not** convert the RegExp to uppercase.
309
311
  * M.find({ email: /an example/ });
310
312
  *
@@ -347,6 +349,7 @@ SchemaString.prototype.uppercase = function(shouldApply) {
347
349
  * Note that `trim` does **not** affect regular expression queries:
348
350
  *
349
351
  * #### Example:
352
+ *
350
353
  * // Mongoose does **not** trim whitespace from the RegExp.
351
354
  * M.find({ name: / some name / });
352
355
  *
package/lib/schema.js CHANGED
@@ -133,6 +133,24 @@ function Schema(obj, options) {
133
133
  this.add(obj);
134
134
  }
135
135
 
136
+ // build virtual paths
137
+ if (options && options.virtuals) {
138
+ const virtuals = options.virtuals;
139
+ const pathNames = Object.keys(virtuals);
140
+ for (const pathName of pathNames) {
141
+ const pathOptions = virtuals[pathName].options ? virtuals[pathName].options : undefined;
142
+ const virtual = this.virtual(pathName, pathOptions);
143
+
144
+ if (virtuals[pathName].get) {
145
+ virtual.get(virtuals[pathName].get);
146
+ }
147
+
148
+ if (virtuals[pathName].set) {
149
+ virtual.set(virtuals[pathName].set);
150
+ }
151
+ }
152
+ }
153
+
136
154
  // check if _id's value is a subdocument (gh-2276)
137
155
  const _idSubDoc = obj && obj._id && utils.isObject(obj._id);
138
156
 
@@ -438,8 +456,8 @@ Schema.prototype.pick = function(paths, options) {
438
456
  Schema.prototype.defaultOptions = function(options) {
439
457
  this._userProvidedOptions = options == null ? {} : utils.clone(options);
440
458
  const baseOptions = this.base && this.base.options || {};
441
-
442
459
  const strict = 'strict' in baseOptions ? baseOptions.strict : true;
460
+ const id = 'id' in baseOptions ? baseOptions.id : true;
443
461
  options = utils.options({
444
462
  strict: strict,
445
463
  strictQuery: 'strict' in this._userProvidedOptions ?
@@ -458,7 +476,7 @@ Schema.prototype.defaultOptions = function(options) {
458
476
  validateBeforeSave: true,
459
477
  // the following are only applied at construction time
460
478
  _id: true,
461
- id: true,
479
+ id: id,
462
480
  typeKey: 'type'
463
481
  }, utils.clone(options));
464
482
 
@@ -1385,6 +1403,7 @@ Schema.prototype.indexedPaths = function indexedPaths() {
1385
1403
  * Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.
1386
1404
  *
1387
1405
  * #### Example:
1406
+ *
1388
1407
  * const s = new Schema({ name: String, nested: { foo: String } });
1389
1408
  * s.virtual('foo').get(() => 42);
1390
1409
  * s.pathType('name'); // "real"
@@ -1849,7 +1868,7 @@ Schema.prototype.index = function(fields, options) {
1849
1868
  *
1850
1869
  * @param {String} key The name of the option to set the value to
1851
1870
  * @param {Object} [value] The value to set the option to, if not passed, the option will be reset to default
1852
- * @see Schema ./
1871
+ * @see Schema #schema_Schema
1853
1872
  * @api public
1854
1873
  */
1855
1874
 
package/lib/schematype.js CHANGED
@@ -1110,7 +1110,7 @@ SchemaType.prototype.ref = function(ref) {
1110
1110
  * @api private
1111
1111
  */
1112
1112
 
1113
- SchemaType.prototype.getDefault = function(scope, init) {
1113
+ SchemaType.prototype.getDefault = function(scope, init, options) {
1114
1114
  let ret;
1115
1115
  if (typeof this.defaultValue === 'function') {
1116
1116
  if (
@@ -1131,6 +1131,10 @@ SchemaType.prototype.getDefault = function(scope, init) {
1131
1131
  ret = utils.clone(ret);
1132
1132
  }
1133
1133
 
1134
+ if (options && options.skipCast) {
1135
+ return this._applySetters(ret, scope);
1136
+ }
1137
+
1134
1138
  const casted = this.applySetters(ret, scope, init, undefined, setOptionsForDefaults);
1135
1139
  if (casted && !Array.isArray(casted) && casted.$isSingleNested) {
1136
1140
  casted.$__parent = scope;
@@ -38,19 +38,12 @@ StateMachine.ctor = function() {
38
38
  StateMachine.apply(this, arguments);
39
39
  this.paths = {};
40
40
  this.states = {};
41
- this.stateNames = states;
42
-
43
- let i = states.length,
44
- state;
45
-
46
- while (i--) {
47
- state = states[i];
48
- this.states[state] = {};
49
- }
50
41
  };
51
42
 
52
43
  ctor.prototype = new StateMachine();
53
44
 
45
+ ctor.prototype.stateNames = states;
46
+
54
47
  states.forEach(function(state) {
55
48
  // Changes the `path`'s state to `state`.
56
49
  ctor.prototype[state] = function(path) {
@@ -76,6 +69,7 @@ StateMachine.prototype._changeState = function _changeState(path, nextState) {
76
69
  if (prevBucket) delete prevBucket[path];
77
70
 
78
71
  this.paths[path] = nextState;
72
+ this.states[nextState] = this.states[nextState] || {};
79
73
  this.states[nextState][path] = true;
80
74
  };
81
75
 
@@ -84,6 +78,9 @@ StateMachine.prototype._changeState = function _changeState(path, nextState) {
84
78
  */
85
79
 
86
80
  StateMachine.prototype.clear = function clear(state) {
81
+ if (this.states[state] == null) {
82
+ return;
83
+ }
87
84
  const keys = Object.keys(this.states[state]);
88
85
  let i = keys.length;
89
86
  let path;
@@ -108,6 +105,17 @@ StateMachine.prototype.clearPath = function clearPath(path) {
108
105
  delete this.states[state][path];
109
106
  };
110
107
 
108
+ /*!
109
+ * Gets the paths for the given state, or empty object `{}` if none.
110
+ */
111
+
112
+ StateMachine.prototype.getStatePaths = function getStatePaths(state) {
113
+ if (this.states[state] != null) {
114
+ return this.states[state];
115
+ }
116
+ return {};
117
+ };
118
+
111
119
  /*!
112
120
  * Checks to see if at least one path is in the states passed in via `arguments`
113
121
  * e.g., this.some('required', 'inited')
@@ -120,6 +128,9 @@ StateMachine.prototype.some = function some() {
120
128
  const _this = this;
121
129
  const what = arguments.length ? arguments : this.stateNames;
122
130
  return Array.prototype.some.call(what, function(state) {
131
+ if (_this.states[state] == null) {
132
+ return false;
133
+ }
123
134
  return Object.keys(_this.states[state]).length;
124
135
  });
125
136
  };
@@ -143,6 +154,9 @@ StateMachine.prototype._iter = function _iter(iterMethod) {
143
154
  const _this = this;
144
155
 
145
156
  const paths = states.reduce(function(paths, state) {
157
+ if (_this.states[state] == null) {
158
+ return paths;
159
+ }
146
160
  return paths.concat(Object.keys(_this.states[state]));
147
161
  }, []);
148
162
 
@@ -142,30 +142,32 @@ MongooseBuffer.mixin = {
142
142
  * Compile other Buffer methods marking this buffer as modified.
143
143
  */
144
144
 
145
- (
146
- // node < 0.5
147
- ('writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' +
148
- 'writeFloat writeDouble fill ' +
149
- 'utf8Write binaryWrite asciiWrite set ' +
150
-
151
- // node >= 0.5
152
- 'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +
153
- 'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' + 'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE')
154
- ).split(' ').forEach(function(method) {
155
- if (!Buffer.prototype[method]) {
156
- return;
157
- }
158
- MongooseBuffer.mixin[method] = function() {
159
- const ret = Buffer.prototype[method].apply(this, arguments);
160
- this._markModified();
161
- return ret;
162
- };
163
- });
145
+ utils.each(
146
+ [
147
+ // node < 0.5
148
+ 'writeUInt8', 'writeUInt16', 'writeUInt32', 'writeInt8', 'writeInt16', 'writeInt32',
149
+ 'writeFloat', 'writeDouble', 'fill',
150
+ 'utf8Write', 'binaryWrite', 'asciiWrite', 'set',
151
+
152
+ // node >= 0.5
153
+ 'writeUInt16LE', 'writeUInt16BE', 'writeUInt32LE', 'writeUInt32BE',
154
+ 'writeInt16LE', 'writeInt16BE', 'writeInt32LE', 'writeInt32BE', 'writeFloatLE', 'writeFloatBE', 'writeDoubleLE', 'writeDoubleBE']
155
+ , function(method) {
156
+ if (!Buffer.prototype[method]) {
157
+ return;
158
+ }
159
+ MongooseBuffer.mixin[method] = function() {
160
+ const ret = Buffer.prototype[method].apply(this, arguments);
161
+ this._markModified();
162
+ return ret;
163
+ };
164
+ });
164
165
 
165
166
  /**
166
167
  * Converts this buffer to its Binary type representation.
167
168
  *
168
169
  * #### SubTypes:
170
+ *
169
171
  * const bson = require('bson')
170
172
  * bson.BSON_BINARY_SUBTYPE_DEFAULT
171
173
  * bson.BSON_BINARY_SUBTYPE_FUNCTION
@@ -175,7 +177,7 @@ MongooseBuffer.mixin = {
175
177
  * bson.BSON_BINARY_SUBTYPE_USER_DEFINED
176
178
  * doc.buffer.toObject(bson.BSON_BINARY_SUBTYPE_USER_DEFINED);
177
179
  *
178
- * @see https://bsonspec.org/#/specification
180
+ * @see bsonspec https://bsonspec.org/#/specification
179
181
  * @param {Hex} [subtype]
180
182
  * @return {Binary}
181
183
  * @api public
@@ -247,7 +249,7 @@ MongooseBuffer.mixin.equals = function(other) {
247
249
  *
248
250
  * doc.buffer.subtype(bson.BSON_BINARY_SUBTYPE_UUID);
249
251
  *
250
- * @see https://bsonspec.org/#/specification
252
+ * @see bsonspec https://bsonspec.org/#/specification
251
253
  * @param {Hex} subtype
252
254
  * @api public
253
255
  * @method subtype
package/lib/types/map.js CHANGED
@@ -68,6 +68,7 @@ class MongooseMap extends Map {
68
68
  * ObjectIds as keys.
69
69
  *
70
70
  * #### Example:
71
+ *
71
72
  * doc.myMap.set('test', 42); // works
72
73
  * doc.myMap.set({ obj: 42 }, 42); // Throws "Mongoose maps only support string keys"
73
74
  *
@@ -197,6 +198,7 @@ class MongooseMap extends Map {
197
198
  * the `flattenMaps` option to convert this map to a POJO instead.
198
199
  *
199
200
  * #### Example:
201
+ *
200
202
  * doc.myMap.toJSON() instanceof Map; // true
201
203
  * doc.myMap.toJSON({ flattenMaps: true }) instanceof Map; // false
202
204
  *
package/lib/utils.js CHANGED
@@ -972,3 +972,11 @@ exports.errorToPOJO = function errorToPOJO(error) {
972
972
  exports.warn = function warn(message) {
973
973
  return process.emitWarning(message, { code: 'MONGOOSE' });
974
974
  };
975
+
976
+
977
+ exports.injectTimestampsOption = function injectTimestampsOption(writeOperation, timestampsOption) {
978
+ if (timestampsOption == null) {
979
+ return;
980
+ }
981
+ writeOperation.timestamps = timestampsOption;
982
+ };
@@ -15,6 +15,7 @@ const VALID_OPTIONS = Object.freeze([
15
15
  'bufferTimeoutMS',
16
16
  'cloneSchemas',
17
17
  'debug',
18
+ 'id',
18
19
  'timestamps.createdAt.immutable',
19
20
  'maxTimeMS',
20
21
  'objectIdGetter',
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "6.4.7",
4
+ "version": "6.5.2",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -19,18 +19,18 @@
19
19
  ],
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "bson": "^4.6.2",
22
+ "bson": "^4.6.5",
23
23
  "kareem": "2.4.1",
24
- "mongodb": "4.7.0",
24
+ "mongodb": "4.8.1",
25
25
  "mpath": "0.9.0",
26
26
  "mquery": "4.0.3",
27
27
  "ms": "2.1.3",
28
28
  "sift": "16.0.0"
29
29
  },
30
30
  "devDependencies": {
31
- "@babel/core": "7.18.6",
32
- "@typescript-eslint/eslint-plugin": "5.30.3",
33
- "@typescript-eslint/parser": "5.30.3",
31
+ "@babel/core": "7.18.10",
32
+ "@typescript-eslint/eslint-plugin": "5.32.0",
33
+ "@typescript-eslint/parser": "5.32.0",
34
34
  "acquit": "1.2.1",
35
35
  "acquit-ignore": "0.2.0",
36
36
  "acquit-require": "0.1.1",
@@ -43,16 +43,16 @@
43
43
  "cheerio": "1.0.0-rc.12",
44
44
  "crypto-browserify": "3.12.0",
45
45
  "dox": "0.9.1",
46
- "eslint": "8.19.0",
46
+ "eslint": "8.21.0",
47
47
  "eslint-plugin-mocha-no-only": "1.1.1",
48
- "highlight.js": "11.5.1",
48
+ "highlight.js": "11.6.0",
49
49
  "lodash.isequal": "4.5.0",
50
50
  "lodash.isequalwith": "4.4.0",
51
- "marked": "4.0.17",
51
+ "marked": "4.0.18",
52
52
  "mkdirp": "^1.0.4",
53
53
  "mocha": "10.0.0",
54
54
  "moment": "2.x",
55
- "mongodb-memory-server": "8.7.2",
55
+ "mongodb-memory-server": "8.8.0",
56
56
  "ncp": "^2.0.0",
57
57
  "nyc": "15.1.0",
58
58
  "pug": "3.0.2",
@@ -64,7 +64,7 @@
64
64
  "tsd": "0.20.0",
65
65
  "typescript": "4.7.4",
66
66
  "uuid": "8.3.2",
67
- "webpack": "5.73.0"
67
+ "webpack": "5.74.0"
68
68
  },
69
69
  "directories": {
70
70
  "lib": "./lib/mongoose"
@@ -77,18 +77,18 @@
77
77
  "docs:copy:tmp:legacy": "rimraf ./docs/5.x && ncp ./tmp ./docs/5.x",
78
78
  "docs:checkout:gh-pages": "git checkout gh-pages",
79
79
  "docs:checkout:legacy": "git checkout 5.x",
80
- "docs:generate": "node website.js",
80
+ "docs:generate": "node ./scripts/website.js",
81
81
  "docs:generate:search": "node docs/search.js",
82
82
  "docs:merge:stable": "git merge master",
83
83
  "docs:merge:legacy": "git merge 5.x",
84
84
  "docs:test": "npm run docs:generate && npm run docs:generate:search",
85
- "docs:view": "node website.js && node static.js",
85
+ "docs:view": "node ./scripts/static.js",
86
86
  "docs:prepare:publish:stable": "npm run docs:checkout:gh-pages && npm run docs:merge:stable && npm run docs:clean:stable && npm run docs:generate && npm run docs:generate:search",
87
87
  "docs:prepare:publish:legacy": "npm run docs:checkout:legacy && npm run docs:merge:legacy && npm run docs:clean:stable && npm run docs:generate && npm run docs:copy:tmp && docs:checkout:gh-pages && docs:copy:tmp:legacy",
88
88
  "lint": "eslint .",
89
89
  "lint-js": "eslint . --ext .js",
90
90
  "lint-ts": "eslint . --ext .ts",
91
- "build-browser": "node build-browser.js",
91
+ "build-browser": "node ./scripts/build-browser.js",
92
92
  "prepublishOnly": "npm run build-browser",
93
93
  "release": "git pull && git push origin master --tags && npm publish",
94
94
  "release-legacy": "git pull origin 5.x && git push origin 5.x --tags && npm publish --tag legacy",