mongoose 8.19.4 → 8.20.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.
package/lib/schema.js CHANGED
@@ -1572,7 +1572,7 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
1572
1572
  let name;
1573
1573
 
1574
1574
  if (utils.isPOJO(type) || type === 'mixed') {
1575
- return new MongooseTypes.Mixed(path, obj);
1575
+ return new MongooseTypes.Mixed(path, obj, null, this);
1576
1576
  }
1577
1577
 
1578
1578
  if (Array.isArray(type) || type === Array || type === 'array' || type === MongooseTypes.Array) {
@@ -1595,7 +1595,7 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
1595
1595
  `${path}: new Schema(...)`);
1596
1596
  }
1597
1597
  }
1598
- return new MongooseTypes.DocumentArray(path, cast, obj);
1598
+ return new MongooseTypes.DocumentArray(path, cast, obj, null, this);
1599
1599
  }
1600
1600
  if (cast &&
1601
1601
  cast[options.typeKey] &&
@@ -1612,14 +1612,14 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
1612
1612
  `${path}: new Schema(...)`);
1613
1613
  }
1614
1614
  }
1615
- return new MongooseTypes.DocumentArray(path, cast[options.typeKey], obj, cast);
1615
+ return new MongooseTypes.DocumentArray(path, cast[options.typeKey], obj, cast, this);
1616
1616
  }
1617
1617
  if (typeof cast !== 'undefined') {
1618
1618
  if (Array.isArray(cast) || cast.type === Array || cast.type == 'Array') {
1619
1619
  if (cast && cast.type == 'Array') {
1620
1620
  cast.type = Array;
1621
1621
  }
1622
- return new MongooseTypes.Array(path, this.interpretAsType(path, cast, options), obj);
1622
+ return new MongooseTypes.Array(path, this.interpretAsType(path, cast, options), obj, null, this);
1623
1623
  }
1624
1624
  }
1625
1625
 
@@ -1660,10 +1660,10 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
1660
1660
 
1661
1661
  const childSchema = new Schema(castFromTypeKey, childSchemaOptions);
1662
1662
  childSchema.$implicitlyCreated = true;
1663
- return new MongooseTypes.DocumentArray(path, childSchema, obj);
1663
+ return new MongooseTypes.DocumentArray(path, childSchema, obj, null, this);
1664
1664
  } else {
1665
1665
  // Special case: empty object becomes mixed
1666
- return new MongooseTypes.Array(path, MongooseTypes.Mixed, obj);
1666
+ return new MongooseTypes.Array(path, MongooseTypes.Mixed, obj, null, this);
1667
1667
  }
1668
1668
  }
1669
1669
 
@@ -1672,7 +1672,7 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
1672
1672
  ? cast[options.typeKey]
1673
1673
  : cast;
1674
1674
  if (Array.isArray(type)) {
1675
- return new MongooseTypes.Array(path, this.interpretAsType(path, type, options), obj);
1675
+ return new MongooseTypes.Array(path, this.interpretAsType(path, type, options), obj, null, this);
1676
1676
  }
1677
1677
 
1678
1678
  name = typeof type === 'string'
@@ -1700,11 +1700,11 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
1700
1700
  }
1701
1701
  }
1702
1702
 
1703
- return new MongooseTypes.Array(path, cast || MongooseTypes.Mixed, obj, options);
1703
+ return new MongooseTypes.Array(path, cast || MongooseTypes.Mixed, obj, options, this);
1704
1704
  }
1705
1705
 
1706
1706
  if (type && type.instanceOfSchema) {
1707
- return new MongooseTypes.Subdocument(type, path, obj);
1707
+ return new MongooseTypes.Subdocument(type, path, obj, this);
1708
1708
  }
1709
1709
 
1710
1710
  if (Buffer.isBuffer(type)) {
@@ -1743,53 +1743,11 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
1743
1743
  'https://bit.ly/mongoose-schematypes for a list of valid schema types.');
1744
1744
  }
1745
1745
 
1746
- if (name === 'Union') {
1747
- obj.parentSchema = this;
1748
- }
1749
- const schemaType = new MongooseTypes[name](path, obj, options);
1750
-
1751
- if (schemaType.$isSchemaMap) {
1752
- createMapNestedSchemaType(this, schemaType, path, obj, options);
1753
- }
1746
+ const schemaType = new MongooseTypes[name](path, obj, options, this);
1754
1747
 
1755
1748
  return schemaType;
1756
1749
  };
1757
1750
 
1758
- /*!
1759
- * ignore
1760
- */
1761
-
1762
- function createMapNestedSchemaType(schema, schemaType, path, obj, options) {
1763
- const mapPath = path + '.$*';
1764
- let _mapType = { type: {} };
1765
- if (utils.hasUserDefinedProperty(obj, 'of')) {
1766
- const isInlineSchema = utils.isPOJO(obj.of) &&
1767
- Object.keys(obj.of).length > 0 &&
1768
- !utils.hasUserDefinedProperty(obj.of, schema.options.typeKey);
1769
- if (isInlineSchema) {
1770
- _mapType = { [schema.options.typeKey]: new Schema(obj.of) };
1771
- } else if (utils.isPOJO(obj.of)) {
1772
- _mapType = Object.assign({}, obj.of);
1773
- } else {
1774
- _mapType = { [schema.options.typeKey]: obj.of };
1775
- }
1776
-
1777
- if (_mapType[schema.options.typeKey] && _mapType[schema.options.typeKey].instanceOfSchema) {
1778
- const subdocumentSchema = _mapType[schema.options.typeKey];
1779
- subdocumentSchema.eachPath((subpath, type) => {
1780
- if (type.options.select === true || type.options.select === false) {
1781
- throw new MongooseError('Cannot use schema-level projections (`select: true` or `select: false`) within maps at path "' + path + '.' + subpath + '"');
1782
- }
1783
- });
1784
- }
1785
-
1786
- if (utils.hasUserDefinedProperty(obj, 'ref')) {
1787
- _mapType.ref = obj.ref;
1788
- }
1789
- }
1790
- schemaType.$__schemaType = schema.interpretAsType(mapPath, _mapType, options);
1791
- }
1792
-
1793
1751
  /**
1794
1752
  * Iterates the schemas paths similar to Array#forEach.
1795
1753
  *
package/lib/schemaType.js CHANGED
@@ -37,10 +37,11 @@ const setOptionsForDefaults = { _skipMarkModified: true };
37
37
  * @param {String} path
38
38
  * @param {SchemaTypeOptions} [options] See [SchemaTypeOptions docs](https://mongoosejs.com/docs/api/schematypeoptions.html)
39
39
  * @param {String} [instance]
40
+ * @param {Schema} [parentSchema]
40
41
  * @api public
41
42
  */
42
43
 
43
- function SchemaType(path, options, instance) {
44
+ function SchemaType(path, options, instance, parentSchema) {
44
45
  this[schemaTypeSymbol] = true;
45
46
  this.path = path;
46
47
  this.instance = instance;
@@ -73,6 +74,7 @@ function SchemaType(path, options, instance) {
73
74
 
74
75
  const Options = this.OptionsConstructor || SchemaTypeOptions;
75
76
  this.options = new Options(options);
77
+ this.parentSchema = parentSchema;
76
78
  this._index = null;
77
79
 
78
80
  if (utils.hasUserDefinedProperty(this.options, 'immutable')) {
@@ -157,6 +159,30 @@ SchemaType.prototype.OptionsConstructor = SchemaTypeOptions;
157
159
 
158
160
  SchemaType.prototype.path;
159
161
 
162
+ /**
163
+ * Returns a plain JavaScript object representing this SchemaType.
164
+ *
165
+ * Typically used by `JSON.stringify()` or when calling `.toJSON()` on a SchemaType instance.
166
+ * Omits certain internal properties such as `parentSchema` that can cause circular references.
167
+ *
168
+ * #### Example:
169
+ *
170
+ * const schema = new Schema({ name: String });
171
+ * const schematype = schema.path('name');
172
+ * console.log(schematype.toJSON());
173
+ *
174
+ * @function toJSON
175
+ * @memberOf SchemaType
176
+ * @instance
177
+ * @api public
178
+ */
179
+
180
+ SchemaType.prototype.toJSON = function toJSON() {
181
+ const res = { ...this };
182
+ delete res.parentSchema;
183
+ return res;
184
+ };
185
+
160
186
  /**
161
187
  * The validators that Mongoose should run to validate properties at this SchemaType's path.
162
188
  *
@@ -1751,7 +1777,7 @@ SchemaType.prototype.checkRequired = function(val) {
1751
1777
 
1752
1778
  SchemaType.prototype.clone = function() {
1753
1779
  const options = Object.assign({}, this.options);
1754
- const schematype = new this.constructor(this.path, options, this.instance);
1780
+ const schematype = new this.constructor(this.path, options, this.instance, this.parentSchema);
1755
1781
  schematype.validators = this.validators.slice();
1756
1782
  if (this.requiredValidator !== undefined) schematype.requiredValidator = this.requiredValidator;
1757
1783
  if (this.defaultValue !== undefined) schematype.defaultValue = this.defaultValue;
@@ -2,7 +2,6 @@
2
2
 
3
3
  const ArrayMethods = require('../../array/methods');
4
4
  const Document = require('../../../document');
5
- const castObjectId = require('../../../cast/objectid');
6
5
  const getDiscriminatorByValue = require('../../../helpers/discriminator/getDiscriminatorByValue');
7
6
  const internalToObjectOptions = require('../../../options').internalToObjectOptions;
8
7
  const utils = require('../../../utils');
@@ -121,23 +120,34 @@ const methods = {
121
120
  *
122
121
  * @return {EmbeddedDocument|null} the subdocument or null if not found.
123
122
  * @param {ObjectId|String|Number|Buffer} id
124
- * @TODO cast to the _id based on schema for proper comparison
125
123
  * @method id
126
124
  * @api public
127
125
  * @memberOf MongooseDocumentArray
128
126
  */
129
127
 
130
128
  id(id) {
131
- let casted;
132
- let sid;
133
- let _id;
129
+ if (id == null) {
130
+ return null;
131
+ }
132
+
133
+ const schemaType = this[arraySchemaSymbol];
134
+ let idSchemaType = null;
135
+
136
+ if (schemaType && schemaType.schema) {
137
+ idSchemaType = schemaType.schema.path('_id');
138
+ } else if (schemaType && schemaType.casterConstructor && schemaType.casterConstructor.schema) {
139
+ idSchemaType = schemaType.casterConstructor.schema.path('_id');
140
+ }
134
141
 
135
- try {
136
- casted = castObjectId(id).toString();
137
- } catch (e) {
138
- casted = null;
142
+ let castedId = null;
143
+ if (idSchemaType) {
144
+ try {
145
+ castedId = idSchemaType.cast(id);
146
+ } catch (_err) {}
139
147
  }
140
148
 
149
+ let _id;
150
+
141
151
  for (const val of this) {
142
152
  if (!val) {
143
153
  continue;
@@ -145,18 +155,20 @@ const methods = {
145
155
 
146
156
  _id = val.get('_id');
147
157
 
148
- if (_id === null || typeof _id === 'undefined') {
158
+ if (_id == null) {
149
159
  continue;
150
160
  } else if (_id instanceof Document) {
151
- sid || (sid = String(id));
152
- if (sid == _id._id) {
161
+ _id = _id.get('_id');
162
+ if (castedId != null && utils.deepEqual(castedId, _id)) {
153
163
  return val;
154
- }
155
- } else if (!isBsonType(id, 'ObjectId') && !isBsonType(_id, 'ObjectId')) {
156
- if (id == _id || utils.deepEqual(id, _id)) {
164
+ } else if (castedId == null && (id == _id || utils.deepEqual(id, _id))) {
165
+ // Backwards compat: compare user-specified param to _id using loose equality
157
166
  return val;
158
167
  }
159
- } else if (casted == _id) {
168
+ } else if (castedId != null && utils.deepEqual(castedId, _id)) {
169
+ return val;
170
+ } else if (castedId == null && (_id == id || utils.deepEqual(id, _id))) {
171
+ // Backwards compat: compare user-specified param to _id using loose equality
160
172
  return val;
161
173
  }
162
174
  }
package/lib/types/map.js CHANGED
@@ -1,6 +1,5 @@
1
1
  'use strict';
2
2
 
3
- const Mixed = require('../schema/mixed');
4
3
  const MongooseError = require('../error/mongooseError');
5
4
  const clone = require('../helpers/clone');
6
5
  const deepEqual = require('../utils').deepEqual;
@@ -41,7 +40,7 @@ class MongooseMap extends Map {
41
40
  this.$__pathRelativeToParent = null;
42
41
  }
43
42
 
44
- this.$__schemaType = schemaType == null ? new Mixed(path) : schemaType;
43
+ this.$__schemaType = schemaType;
45
44
 
46
45
  this.$__runDeferred();
47
46
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "8.19.4",
4
+ "version": "8.20.0",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -18,7 +18,7 @@ declare module 'mongoose' {
18
18
  * * TQueryHelpers - Object with any helpers that should be mixed into the Query type
19
19
  * * DocType - the type of the actual Document created
20
20
  */
21
- class Document<T = unknown, TQueryHelpers = any, DocType = any, TVirtuals = Record<string, any>, TSchemaOptions = {}> {
21
+ class Document<T = Types.ObjectId, TQueryHelpers = any, DocType = any, TVirtuals = Record<string, any>, TSchemaOptions = {}> {
22
22
  constructor(doc?: any);
23
23
 
24
24
  /** This documents _id. */