mongoose 8.15.1 → 8.15.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.
package/lib/document.js CHANGED
@@ -1302,7 +1302,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
1302
1302
  let cur = this._doc;
1303
1303
  let curPath = '';
1304
1304
  for (i = 0; i < parts.length - 1; ++i) {
1305
- cur = cur[parts[i]];
1305
+ cur = cur instanceof Map ? cur.get(parts[i]) : cur[parts[i]];
1306
1306
  curPath += (curPath.length !== 0 ? '.' : '') + parts[i];
1307
1307
  if (!cur) {
1308
1308
  this.$set(curPath, {});
@@ -1433,9 +1433,9 @@ Document.prototype.$set = function $set(path, val, type, options) {
1433
1433
  setterContext = getDeepestSubdocumentForPath(this, parts, this.schema);
1434
1434
  }
1435
1435
  if (options != null && options.overwriteImmutable) {
1436
- val = schema.applySetters(val, setterContext, false, priorVal, { overwriteImmutable: true });
1436
+ val = schema.applySetters(val, setterContext, false, priorVal, { path, overwriteImmutable: true });
1437
1437
  } else {
1438
- val = schema.applySetters(val, setterContext, false, priorVal);
1438
+ val = schema.applySetters(val, setterContext, false, priorVal, { path });
1439
1439
  }
1440
1440
  }
1441
1441
 
@@ -2710,7 +2710,13 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip, isNestedValidate
2710
2710
  Object.keys(doc.$__.activePaths.getStatePaths('init')).forEach(addToPaths);
2711
2711
  Object.keys(doc.$__.activePaths.getStatePaths('modify')).forEach(addToPaths);
2712
2712
  Object.keys(doc.$__.activePaths.getStatePaths('default')).forEach(addToPaths);
2713
- function addToPaths(p) { paths.add(p); }
2713
+ function addToPaths(p) {
2714
+ if (p.endsWith('.$*')) {
2715
+ // Skip $* paths - they represent map schemas, not actual document paths
2716
+ return;
2717
+ }
2718
+ paths.add(p);
2719
+ }
2714
2720
 
2715
2721
  if (!isNestedValidate) {
2716
2722
  // If we're validating a subdocument, all this logic will run anyway on the top-level document, so skip for subdocuments.
@@ -2750,6 +2756,9 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip, isNestedValidate
2750
2756
  }
2751
2757
 
2752
2758
  const subdocParent = subdoc.$parent();
2759
+ if (subdocParent == null) {
2760
+ throw new Error('Cannot validate subdocument that does not have a parent');
2761
+ }
2753
2762
  if (doc.$isModified(fullPathToSubdoc, null, modifiedPaths) &&
2754
2763
  // Avoid using isDirectModified() here because that does additional checks on whether the parent path
2755
2764
  // is direct modified, which can cause performance issues re: gh-14897
@@ -144,7 +144,24 @@ module.exports = function assignVals(o) {
144
144
  if (Array.isArray(valueToSet)) {
145
145
  valueToSet = valueToSet.map(v => v == null ? void 0 : v);
146
146
  }
147
- mpath.set(_path, valueToSet, docs[i], void 0, setValue, false);
147
+ mpath.set(
148
+ _path,
149
+ valueToSet,
150
+ docs[i],
151
+ // Handle setting paths underneath maps using $* by converting arrays into maps of values
152
+ function lookup(obj, part, val) {
153
+ if (arguments.length >= 3) {
154
+ obj[part] = val;
155
+ return obj[part];
156
+ }
157
+ if (obj instanceof Map && part === '$*') {
158
+ return [...obj.values()];
159
+ }
160
+ return obj[part];
161
+ },
162
+ setValue,
163
+ false
164
+ );
148
165
  continue;
149
166
  }
150
167
 
@@ -58,6 +58,37 @@ function getVirtual(schema, name) {
58
58
  nestedSchemaPath += (nestedSchemaPath.length > 0 ? '.' : '') + cur;
59
59
  cur = '';
60
60
  continue;
61
+ } else if (schema.paths[cur]?.$isSchemaMap && schema.paths[cur].$__schemaType?.schema) {
62
+ schema = schema.paths[cur].$__schemaType.schema;
63
+ ++i;
64
+ const rest = parts.slice(i + 1).join('.');
65
+
66
+ if (schema.virtuals[rest]) {
67
+ if (i === parts.length - 2) {
68
+ return {
69
+ virtual: schema.virtuals[rest],
70
+ nestedSchemaPath: [nestedSchemaPath, cur, '$*'].filter(v => !!v).join('.')
71
+ };
72
+ }
73
+ continue;
74
+ }
75
+
76
+ if (i + 1 < parts.length && schema.discriminators) {
77
+ for (const key of Object.keys(schema.discriminators)) {
78
+ const res = getVirtual(schema.discriminators[key], rest);
79
+ if (res != null) {
80
+ const _path = [nestedSchemaPath, cur, res.nestedSchemaPath, '$*'].
81
+ filter(v => !!v).join('.');
82
+ return {
83
+ virtual: res.virtual,
84
+ nestedSchemaPath: _path
85
+ };
86
+ }
87
+ }
88
+ }
89
+
90
+ nestedSchemaPath += (nestedSchemaPath.length > 0 ? '.' : '') + '$*' + cur;
91
+ cur = '';
61
92
  }
62
93
 
63
94
  if (schema.discriminators) {
@@ -147,6 +147,9 @@ module.exports = function(query, schema, castedDoc, options, callback) {
147
147
  return callback(null);
148
148
  }
149
149
  }
150
+ if (schemaPath.$isSingleNested) {
151
+ alreadyValidated.push(updates[i]);
152
+ }
150
153
 
151
154
  schemaPath.doValidate(v, function(err) {
152
155
  if (schemaPath.schema != null &&
@@ -246,4 +249,3 @@ module.exports = function(query, schema, castedDoc, options, callback) {
246
249
  };
247
250
  }
248
251
  };
249
-
package/lib/model.js CHANGED
@@ -460,8 +460,8 @@ Model.prototype.$__handleSave = function(options, callback) {
460
460
  return;
461
461
  }
462
462
 
463
- // store the modified paths before the document is reset
464
- this.$__.modifiedPaths = this.modifiedPaths();
463
+ // store the modified paths before the document is reset in case we need to generate version error.
464
+ this.$__.modifiedPaths = this.modifiedPaths().concat(Object.keys(this.$__.activePaths.getStatePaths('default')));
465
465
  this.$__reset();
466
466
 
467
467
  _setIsNew(this, false);
@@ -562,13 +562,13 @@ Model.prototype.$__save = function(options, callback) {
562
562
  * ignore
563
563
  */
564
564
 
565
- function generateVersionError(doc, modifiedPaths) {
565
+ function generateVersionError(doc, modifiedPaths, defaultPaths) {
566
566
  const key = doc.$__schema.options.versionKey;
567
567
  if (!key) {
568
568
  return null;
569
569
  }
570
570
  const version = doc.$__getValue(key) || 0;
571
- return new VersionError(doc, version, modifiedPaths);
571
+ return new VersionError(doc, version, modifiedPaths.concat(defaultPaths));
572
572
  }
573
573
 
574
574
  /**
@@ -626,7 +626,11 @@ Model.prototype.save = async function save(options) {
626
626
  if (this.$__.timestamps != null) {
627
627
  options.timestamps = this.$__.timestamps;
628
628
  }
629
- this.$__.$versionError = generateVersionError(this, this.modifiedPaths());
629
+ this.$__.$versionError = generateVersionError(
630
+ this,
631
+ this.modifiedPaths(),
632
+ Object.keys(this.$__.activePaths.getStatePaths('default'))
633
+ );
630
634
 
631
635
  if (parallelSave) {
632
636
  this.$__handleReject(parallelSave);
package/lib/schema.js CHANGED
@@ -1482,10 +1482,24 @@ function getMapPath(schema, path) {
1482
1482
  return null;
1483
1483
  }
1484
1484
  for (const val of schema.mapPaths) {
1485
- const _path = val.path;
1486
- const re = new RegExp('^' + _path.replace(/\.\$\*/g, '\\.[^.]+') + '$');
1487
- if (re.test(path)) {
1488
- return schema.paths[_path];
1485
+ const cleanPath = val.path.replace(/\.\$\*/g, '');
1486
+ if (path === cleanPath || (path.startsWith(cleanPath + '.') && path.slice(cleanPath.length + 1).indexOf('.') === -1)) {
1487
+ return val;
1488
+ } else if (val.schema && path.startsWith(cleanPath + '.')) {
1489
+ let remnant = path.slice(cleanPath.length + 1);
1490
+ remnant = remnant.slice(remnant.indexOf('.') + 1);
1491
+ return val.schema.paths[remnant];
1492
+ } else if (val.$isSchemaMap && path.startsWith(cleanPath + '.')) {
1493
+ let remnant = path.slice(cleanPath.length + 1);
1494
+ remnant = remnant.slice(remnant.indexOf('.') + 1);
1495
+ const presplitPath = val.$__schemaType._presplitPath;
1496
+ if (remnant.indexOf('.') === -1 && presplitPath[presplitPath.length - 1] === '$*') {
1497
+ // Handle map of map of primitives
1498
+ return val.$__schemaType;
1499
+ } else if (remnant.indexOf('.') !== -1 && val.$__schemaType.schema && presplitPath[presplitPath.length - 1] === '$*') {
1500
+ // map of map of subdocs (recursive)
1501
+ return val.$__schemaType.schema.path(remnant.slice(remnant.indexOf('.') + 1));
1502
+ }
1489
1503
  }
1490
1504
  }
1491
1505
 
@@ -2608,6 +2622,10 @@ Schema.prototype.virtual = function(name, options) {
2608
2622
  const remnant = parts.slice(i + 1).join('.');
2609
2623
  this.paths[cur].schema.virtual(remnant, options);
2610
2624
  break;
2625
+ } else if (this.paths[cur].$isSchemaMap) {
2626
+ const remnant = parts.slice(i + 2).join('.');
2627
+ this.paths[cur].$__schemaType.schema.virtual(remnant, options);
2628
+ break;
2611
2629
  }
2612
2630
 
2613
2631
  cur += '.' + parts[i + 1];
@@ -4,7 +4,6 @@
4
4
 
5
5
  'use strict';
6
6
 
7
- const Document = require('../../document');
8
7
  const mongooseArrayMethods = require('./methods');
9
8
 
10
9
  const arrayAtomicsSymbol = require('../../helpers/symbols').arrayAtomicsSymbol;
@@ -73,11 +72,7 @@ function MongooseArray(values, path, doc, schematype) {
73
72
  internals[arrayAtomicsSymbol] = values[arrayAtomicsSymbol];
74
73
  }
75
74
 
76
- // Because doc comes from the context of another function, doc === global
77
- // can happen if there was a null somewhere up the chain (see #3020)
78
- // RB Jun 17, 2015 updated to check for presence of expected paths instead
79
- // to make more proof against unusual node environments
80
- if (doc != null && doc instanceof Document) {
75
+ if (doc != null && doc.$__) {
81
76
  internals[arrayParentSymbol] = doc;
82
77
  internals[arraySchemaSymbol] = schematype || doc.schema.path(path);
83
78
  }
@@ -6,7 +6,6 @@
6
6
 
7
7
  const ArrayMethods = require('../array/methods');
8
8
  const DocumentArrayMethods = require('./methods');
9
- const Document = require('../../document');
10
9
 
11
10
  const arrayAtomicsSymbol = require('../../helpers/symbols').arrayAtomicsSymbol;
12
11
  const arrayAtomicsBackupSymbol = require('../../helpers/symbols').arrayAtomicsBackupSymbol;
@@ -51,11 +50,7 @@ function MongooseDocumentArray(values, path, doc, schematype) {
51
50
  internals[arrayPathSymbol] = path;
52
51
  internals.__array = __array;
53
52
 
54
- // Because doc comes from the context of another function, doc === global
55
- // can happen if there was a null somewhere up the chain (see #3020 && #3034)
56
- // RB Jun 17, 2015 updated to check for presence of expected paths instead
57
- // to make more proof against unusual node environments
58
- if (doc && doc instanceof Document) {
53
+ if (doc && doc.$__) {
59
54
  internals[arrayParentSymbol] = doc;
60
55
  internals[arraySchemaSymbol] = doc.$__schema.path(path);
61
56
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "8.15.1",
4
+ "version": "8.15.2",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -29,12 +29,12 @@
29
29
  "sift": "17.1.3"
30
30
  },
31
31
  "devDependencies": {
32
- "@babel/core": "7.27.1",
33
- "@babel/preset-env": "7.27.1",
32
+ "@babel/core": "7.27.4",
33
+ "@babel/preset-env": "7.27.2",
34
34
  "@mongodb-js/mongodb-downloader": "^0.3.9",
35
35
  "@typescript-eslint/eslint-plugin": "^8.19.1",
36
36
  "@typescript-eslint/parser": "^8.19.1",
37
- "acquit": "1.3.0",
37
+ "acquit": "1.4.0",
38
38
  "acquit-ignore": "0.2.1",
39
39
  "acquit-require": "0.1.1",
40
40
  "ajv": "8.17.1",
@@ -53,10 +53,10 @@
53
53
  "highlight.js": "11.11.1",
54
54
  "lodash.isequal": "4.5.0",
55
55
  "lodash.isequalwith": "4.4.0",
56
- "markdownlint-cli2": "^0.17.1",
57
- "marked": "15.0.11",
56
+ "markdownlint-cli2": "^0.18.1",
57
+ "marked": "15.0.12",
58
58
  "mkdirp": "^3.0.1",
59
- "mocha": "11.2.2",
59
+ "mocha": "11.5.0",
60
60
  "moment": "2.30.1",
61
61
  "mongodb-memory-server": "10.1.4",
62
62
  "mongodb-runner": "^5.8.2",
@@ -69,7 +69,7 @@
69
69
  "tsd": "0.32.0",
70
70
  "typescript": "5.8.3",
71
71
  "uuid": "11.1.0",
72
- "webpack": "5.99.7"
72
+ "webpack": "5.99.9"
73
73
  },
74
74
  "directories": {
75
75
  "lib": "./lib/mongoose"
@@ -102,6 +102,7 @@
102
102
  "release-6x": "git pull origin 6.x && git push origin 6.x && git push origin 6.x --tags && npm publish --tag 6x",
103
103
  "mongo": "node ./tools/repl.js",
104
104
  "publish-7x": "npm publish --tag 7x",
105
+ "create-separate-require-instance": "rm -rf ./node_modules/mongoose-separate-require-instance && node ./scripts/create-tarball && tar -xzf mongoose.tgz -C ./node_modules && mv ./node_modules/package ./node_modules/mongoose-separate-require-instance",
105
106
  "test": "mocha --exit ./test/*.test.js",
106
107
  "test-deno": "deno run --allow-env --allow-read --allow-net --allow-run --allow-sys --allow-write ./test/deno.mjs",
107
108
  "test-rs": "START_REPLICA_SET=1 mocha --timeout 30000 --exit ./test/*.test.js",
package/types/models.d.ts CHANGED
@@ -482,7 +482,7 @@ declare module 'mongoose' {
482
482
  * Shortcut for creating a new Document from existing raw data, pre-saved in the DB.
483
483
  * The document returned has no paths marked as modified initially.
484
484
  */
485
- hydrate(obj: any, projection?: AnyObject, options?: HydrateOptions): THydratedDocumentType;
485
+ hydrate(obj: any, projection?: ProjectionType<TRawDocType>, options?: HydrateOptions): THydratedDocumentType;
486
486
 
487
487
  /**
488
488
  * This function is responsible for building [indexes](https://www.mongodb.com/docs/manual/indexes/),