mongoose 6.7.2 → 6.7.3

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/lib/document.js CHANGED
@@ -220,6 +220,17 @@ function Document(obj, fields, skipId, options) {
220
220
  * const user = await User.findOne({ name: 'John Smith' });
221
221
  * user.$isNew; // false
222
222
  *
223
+ * Mongoose sets `$isNew` to `false` immediately after `save()` succeeds.
224
+ * That means Mongoose sets `$isNew` to false **before** `post('save')` hooks run.
225
+ * In `post('save')` hooks, `$isNew` will be `false` if `save()` succeeded.
226
+ *
227
+ * #### Example:
228
+ *
229
+ * userSchema.post('save', function() {
230
+ * this.$isNew; // false
231
+ * });
232
+ * await User.create({ name: 'John Smith' });
233
+ *
223
234
  * For subdocuments, `$isNew` is true if either the parent has `$isNew` set,
224
235
  * or if you create a new subdocument.
225
236
  *
@@ -1468,13 +1479,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
1468
1479
  const doc = this.$isSubdocument ? this.ownerDocument() : this;
1469
1480
  savedState = doc.$__.savedState;
1470
1481
  savedStatePath = this.$isSubdocument ? this.$__.fullPath + '.' + path : path;
1471
- if (savedState != null) {
1472
- const firstDot = savedStatePath.indexOf('.');
1473
- const topLevelPath = firstDot === -1 ? savedStatePath : savedStatePath.slice(0, firstDot);
1474
- if (!savedState.hasOwnProperty(topLevelPath)) {
1475
- savedState[topLevelPath] = utils.clone(doc.$__getValue(topLevelPath));
1476
- }
1477
- }
1482
+ doc.$__saveInitialState(savedStatePath);
1478
1483
  }
1479
1484
 
1480
1485
  this.$__set(pathToMark, path, options, constructing, parts, schema, val, priorVal);
@@ -1583,6 +1588,10 @@ Document.prototype.$__shouldModify = function(pathToMark, path, options, constru
1583
1588
  if (this.$isNew) {
1584
1589
  return true;
1585
1590
  }
1591
+ // Is path already modified? If so, always modify. We may unmark modified later.
1592
+ if (path in this.$__.activePaths.getStatePaths('modify')) {
1593
+ return true;
1594
+ }
1586
1595
 
1587
1596
  // Re: the note about gh-7196, `val` is the raw value without casting or
1588
1597
  // setters if the full path is under a single nested subdoc because we don't
@@ -1780,11 +1789,10 @@ Document.prototype.$inc = function $inc(path, val) {
1780
1789
 
1781
1790
  const currentValue = this.$__getValue(path) || 0;
1782
1791
 
1783
- this.$__setValue(path, currentValue + val);
1784
-
1785
1792
  this.$__.primitiveAtomics = this.$__.primitiveAtomics || {};
1786
1793
  this.$__.primitiveAtomics[path] = { $inc: val };
1787
1794
  this.markModified(path);
1795
+ this.$__setValue(path, currentValue + val);
1788
1796
 
1789
1797
  return this;
1790
1798
  };
@@ -1927,6 +1935,8 @@ Document.prototype.$__path = function(path) {
1927
1935
  */
1928
1936
 
1929
1937
  Document.prototype.markModified = function(path, scope) {
1938
+ this.$__saveInitialState(path);
1939
+
1930
1940
  this.$__.activePaths.modify(path);
1931
1941
  if (scope != null && !this.$isSubdocument) {
1932
1942
  this.$__.pathsToScopes = this.$__pathsToScopes || {};
@@ -1934,6 +1944,22 @@ Document.prototype.markModified = function(path, scope) {
1934
1944
  }
1935
1945
  };
1936
1946
 
1947
+ /*!
1948
+ * ignore
1949
+ */
1950
+
1951
+ Document.prototype.$__saveInitialState = function $__saveInitialState(path) {
1952
+ const savedState = this.$__.savedState;
1953
+ const savedStatePath = path;
1954
+ if (savedState != null) {
1955
+ const firstDot = savedStatePath.indexOf('.');
1956
+ const topLevelPath = firstDot === -1 ? savedStatePath : savedStatePath.slice(0, firstDot);
1957
+ if (!savedState.hasOwnProperty(topLevelPath)) {
1958
+ savedState[topLevelPath] = utils.clone(this.$__getValue(topLevelPath));
1959
+ }
1960
+ }
1961
+ };
1962
+
1937
1963
  /**
1938
1964
  * Clears the modified state on the specified path.
1939
1965
  *
@@ -3379,6 +3405,7 @@ Document.prototype.$__dirty = function() {
3379
3405
  schema: _this.$__path(path)
3380
3406
  };
3381
3407
  });
3408
+
3382
3409
  // gh-2558: if we had to set a default and the value is not undefined,
3383
3410
  // we have to save as well
3384
3411
  all = all.concat(this.$__.activePaths.map('default', function(path) {
@@ -28,7 +28,7 @@ module.exports = function setupTimestamps(schema, timestamps) {
28
28
  schema.$timestamps = { createdAt: createdAt, updatedAt: updatedAt };
29
29
 
30
30
  if (createdAt && !schema.paths[createdAt]) {
31
- const baseImmutableCreatedAt = schema.base.get('timestamps.createdAt.immutable');
31
+ const baseImmutableCreatedAt = schema.base != null ? schema.base.get('timestamps.createdAt.immutable') : null;
32
32
  const immutable = baseImmutableCreatedAt != null ? baseImmutableCreatedAt : true;
33
33
  schemaAdditions[createdAt] = { [schema.options.typeKey || 'type']: Date, immutable };
34
34
  }
package/lib/index.js CHANGED
@@ -205,7 +205,6 @@ Mongoose.prototype.setDriver = function setDriver(driver) {
205
205
  * - 'returnOriginal': If `false`, changes the default `returnOriginal` option to `findOneAndUpdate()`, `findByIdAndUpdate`, and `findOneAndReplace()` to false. This is equivalent to setting the `new` option to `true` for `findOneAndX()` calls by default. Read our [`findOneAndUpdate()` tutorial](/docs/tutorials/findoneandupdate.html) for more information.
206
206
  * - 'bufferCommands': enable/disable mongoose's buffering mechanism for all connections and models
207
207
  * - 'cloneSchemas': `false` by default. Set to `true` to `clone()` all schemas before compiling into a model.
208
- * - 'debug': If `true`, prints the operations mongoose sends to MongoDB to the console. If a writable stream is passed, it will log to that stream, without colorization. If a callback function is passed, it will receive the collection name, the method name, then all arugments passed to the method. For example, if you wanted to replicate the default logging, you could output from the callback `Mongoose: ${collectionName}.${methodName}(${methodArgs.join(', ')})`.
209
208
  * - 'timestamps.createdAt.immutable': `true` by default. If `false`, it will change the `createdAt` field to be [`immutable: false`](https://mongoosejs.com/docs/api/schematype.html#schematype_SchemaType-immutable) which means you can update the `createdAt`
210
209
  * - 'maxTimeMS': If set, attaches [maxTimeMS](https://docs.mongodb.com/manual/reference/operator/meta/maxTimeMS/) to every query
211
210
  * - 'objectIdGetter': `true` by default. Mongoose adds a getter to MongoDB ObjectId's called `_id` that returns `this` for convenience with populate. Set this to false to remove the getter.
package/lib/model.js CHANGED
@@ -4556,7 +4556,7 @@ Model.validate = function validate(obj, pathsToValidate, context, callback) {
4556
4556
  * - match: optional query conditions to match
4557
4557
  * - model: optional name of the model to use for population
4558
4558
  * - options: optional query options like sort, limit, etc
4559
- * - justOne: optional boolean, if true Mongoose will always set `path` to an array. Inferred from schema by default.
4559
+ * - justOne: optional boolean, if true Mongoose will always set `path` to a document, or `null` if no document was found. If false, Mongoose will always set `path` to an array, which will be empty if no documents are found. Inferred from schema by default.
4560
4560
  * - strictPopulate: optional boolean, set to `false` to allow populating paths that aren't in the schema.
4561
4561
  *
4562
4562
  * #### Example:
package/lib/query.js CHANGED
@@ -4574,8 +4574,11 @@ Query.prototype.updateMany = function(conditions, doc, options, callback) {
4574
4574
  * #### Example:
4575
4575
  *
4576
4576
  * const res = await Person.updateOne({ name: 'Jean-Luc Picard' }, { ship: 'USS Enterprise' });
4577
- * res.n; // Number of documents matched
4578
- * res.nModified; // Number of documents modified
4577
+ * res.acknowledged; // Indicates if this write result was acknowledged. If not, then all other members of this result will be undefined.
4578
+ * res.matchedCount; // Number of documents that matched the filter
4579
+ * res.modifiedCount; // Number of documents that were modified
4580
+ * res.upsertedCount; // Number of documents that were upserted
4581
+ * res.upsertedId; // Identifier of the inserted document (if an upsert took place)
4579
4582
  *
4580
4583
  * This function triggers the following middleware.
4581
4584
  *
@@ -4638,8 +4641,11 @@ Query.prototype.updateOne = function(conditions, doc, options, callback) {
4638
4641
  * #### Example:
4639
4642
  *
4640
4643
  * const res = await Person.replaceOne({ _id: 24601 }, { name: 'Jean Valjean' });
4641
- * res.n; // Number of documents matched
4642
- * res.nModified; // Number of documents modified
4644
+ * res.acknowledged; // Indicates if this write result was acknowledged. If not, then all other members of this result will be undefined.
4645
+ * res.matchedCount; // Number of documents that matched the filter
4646
+ * res.modifiedCount; // Number of documents that were modified
4647
+ * res.upsertedCount; // Number of documents that were upserted
4648
+ * res.upsertedId; // Identifier of the inserted document (if an upsert took place)
4643
4649
  *
4644
4650
  * This function triggers the following middleware.
4645
4651
  *
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "6.7.2",
4
+ "version": "6.7.3",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -190,9 +190,6 @@ declare module 'mongoose' {
190
190
  /** Returns the list of paths that have been modified. */
191
191
  modifiedPaths(options?: { includeChildren?: boolean }): Array<string>;
192
192
 
193
- /** The name of the model */
194
- modelName: string;
195
-
196
193
  /**
197
194
  * Overwrite all values in this document with the values of `obj`, except
198
195
  * for immutable properties. Behaves similarly to `set()`, except for it
@@ -213,7 +213,7 @@ declare module 'mongoose' {
213
213
 
214
214
  export interface ReplaceWith {
215
215
  /** [`$replaceWith` reference](https://docs.mongodb.com/manual/reference/operator/aggregation/replaceWith/) */
216
- $replaceWith: ObjectExpressionOperator | { [field: string]: Expression };
216
+ $replaceWith: ObjectExpressionOperator | { [field: string]: Expression } | `$${string}`;
217
217
  }
218
218
 
219
219
  export interface Sample {
@@ -26,8 +26,9 @@ declare module 'mongoose' {
26
26
  /** deep populate */
27
27
  populate?: string | PopulateOptions | (string | PopulateOptions)[];
28
28
  /**
29
- * If true Mongoose will always set `path` to an array, if false Mongoose will
30
- * always set `path` to a document. Inferred from schema by default.
29
+ * If true Mongoose will always set `path` to a document, or `null` if no document was found.
30
+ * If false Mongoose will always set `path` to an array, which will be empty if no documents are found.
31
+ * Inferred from schema by default.
31
32
  */
32
33
  justOne?: boolean;
33
34
  /** transform function to call on every populated doc */