mongoose 9.7.1 → 9.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/eslint.config.mjs CHANGED
@@ -15,7 +15,10 @@ export default defineConfig([
15
15
  '!**/.*',
16
16
  '**/node_modules',
17
17
  '**/.git',
18
- '**/data'
18
+ '**/data',
19
+ '**/docs/3.*/**',
20
+ '**/docs/5.*/**',
21
+ '**/docs/vendor/*'
19
22
  ]),
20
23
  js.configs.recommended,
21
24
  // general options
package/lib/document.js CHANGED
@@ -1948,7 +1948,9 @@ Document.prototype.get = function(path, type, options) {
1948
1948
 
1949
1949
  // Fast path if we know we're just accessing top-level path on the document:
1950
1950
  // just get the schema path, avoid `$__path()` because that does string manipulation
1951
- let schema = noDottedPath ? this.$__schema.paths[path] : this.$__path(path);
1951
+ let schema = noDottedPath ?
1952
+ Object.hasOwn(this.$__schema.paths, path) ? this.$__schema.paths[path] : undefined :
1953
+ this.$__path(path);
1952
1954
  if (schema == null) {
1953
1955
  schema = this.$__schema.virtualpath(path);
1954
1956
 
@@ -1958,7 +1960,7 @@ Document.prototype.get = function(path, type, options) {
1958
1960
  }
1959
1961
 
1960
1962
  if (noDottedPath) {
1961
- let obj = this._doc[path];
1963
+ let obj = Object.hasOwn(this._doc, path) ? this._doc[path] : undefined;
1962
1964
  if (adhoc) {
1963
1965
  obj = adhoc.cast(obj);
1964
1966
  }
@@ -1985,6 +1987,10 @@ Document.prototype.get = function(path, type, options) {
1985
1987
  }
1986
1988
 
1987
1989
  for (let i = 0, l = pieces.length; i < l; i++) {
1990
+ if (specialProperties.has(pieces[i])) {
1991
+ return undefined;
1992
+ }
1993
+
1988
1994
  if (obj?._doc) {
1989
1995
  obj = obj._doc;
1990
1996
  }
@@ -2006,7 +2012,7 @@ Document.prototype.get = function(path, type, options) {
2006
2012
 
2007
2013
  if (schema != null && options.getters !== false) {
2008
2014
  obj = schema.applyGetters(obj, this);
2009
- } else if (this.$__schema.nested[path] && options.virtuals) {
2015
+ } else if (Object.hasOwn(this.$__schema.nested, path) && options.virtuals) {
2010
2016
  // Might need to apply virtuals if this is a nested path
2011
2017
  return applyVirtuals(this, clone(obj) || {}, { path: path });
2012
2018
  }
package/lib/schema.js CHANGED
@@ -1268,7 +1268,7 @@ reserved.collection = 1;
1268
1268
 
1269
1269
  Schema.prototype.path = function(path, obj) {
1270
1270
  if (obj === undefined) {
1271
- if (this.paths[path] != null) {
1271
+ if (Object.hasOwn(this.paths, path)) {
1272
1272
  return this.paths[path];
1273
1273
  }
1274
1274
  // Convert to '.$' to check subpaths re: gh-6405
@@ -1296,9 +1296,15 @@ Schema.prototype.path = function(path, obj) {
1296
1296
  : undefined;
1297
1297
  }
1298
1298
 
1299
+ const subpaths = path.indexOf('.') === -1 ? [path] : path.split('.');
1300
+ const last = subpaths.pop();
1301
+ if (utils.specialProperties.has(last)) {
1302
+ throw new MongooseError('Cannot set special property `' + last + '` on a schema');
1303
+ }
1304
+
1299
1305
  // some path names conflict with document methods
1300
- const firstPieceOfPath = path.split('.')[0];
1301
- if (reserved[firstPieceOfPath] && !this.options.suppressReservedKeysWarning) {
1306
+ const firstPieceOfPath = subpaths.length === 0 ? last : subpaths[0];
1307
+ if (Object.hasOwn(reserved, firstPieceOfPath) && !this.options.suppressReservedKeysWarning) {
1302
1308
  const errorMessage = `\`${firstPieceOfPath}\` is a reserved schema pathname and may break some functionality. ` +
1303
1309
  'You are allowed to use it, but use at your own risk. ' +
1304
1310
  'To disable this warning pass `suppressReservedKeysWarning` as a schema option.';
@@ -1311,8 +1317,6 @@ Schema.prototype.path = function(path, obj) {
1311
1317
  }
1312
1318
 
1313
1319
  // update the tree
1314
- const subpaths = path.split(/\./);
1315
- const last = subpaths.pop();
1316
1320
  let branch = this.tree;
1317
1321
  let fullPath = '';
1318
1322
 
@@ -1536,7 +1540,7 @@ function getMapPath(schema, path) {
1536
1540
  } else if (val.schema && path.startsWith(cleanPath + '.')) {
1537
1541
  let remnant = path.slice(cleanPath.length + 1);
1538
1542
  remnant = remnant.slice(remnant.indexOf('.') + 1);
1539
- return val.schema.paths[remnant];
1543
+ return val.schema.path(remnant);
1540
1544
  } else if (val.$isSchemaMap && path.startsWith(cleanPath + '.')) {
1541
1545
  let remnant = path.slice(cleanPath.length + 1);
1542
1546
  remnant = remnant.slice(remnant.indexOf('.') + 1);
@@ -3026,7 +3030,7 @@ Schema.prototype._getPathType = function(path) {
3026
3030
  };
3027
3031
  }
3028
3032
  return { schema: foundschema, pathType: 'real' };
3029
- } else if (p === parts.length && schema.nested[trypath]) {
3033
+ } else if (p === parts.length && Object.hasOwn(schema.nested, trypath)) {
3030
3034
  return { schema: schema, pathType: 'nested' };
3031
3035
  }
3032
3036
  }
@@ -12,6 +12,7 @@ const arrayPathSymbol = require('../../../helpers/symbols').arrayPathSymbol;
12
12
  const arraySchemaSymbol = require('../../../helpers/symbols').arraySchemaSymbol;
13
13
  const documentArrayParent = require('../../../helpers/symbols').documentArrayParent;
14
14
 
15
+ const _baseReverse = Array.prototype.reverse;
15
16
  const _baseToString = Array.prototype.toString;
16
17
 
17
18
  const methods = {
@@ -211,7 +212,7 @@ const methods = {
211
212
  },
212
213
 
213
214
  /**
214
- * Wraps [`Array#push`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/push) with proper change tracking.
215
+ * Wraps [`Array#push`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push) with proper change tracking.
215
216
  *
216
217
  * @param {...object} [args]
217
218
  * @api public
@@ -220,8 +221,37 @@ const methods = {
220
221
  */
221
222
 
222
223
  push() {
224
+ const shouldReindex = _shouldReindexAfterPush(arguments);
223
225
  const ret = ArrayMethods.push.apply(this, arguments);
224
226
 
227
+ if (shouldReindex) {
228
+ _updateSubdocIndexes(this);
229
+ }
230
+ _updateParentPopulated(this);
231
+
232
+ return ret;
233
+ },
234
+
235
+ /**
236
+ * Wraps [`Array#pop`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop) with proper change tracking.
237
+ * @api private
238
+ */
239
+
240
+ pop() {
241
+ const ret = ArrayMethods.pop.apply(this, arguments);
242
+
243
+ _updateParentPopulated(this);
244
+
245
+ return ret;
246
+ },
247
+
248
+ /*!
249
+ * ignore
250
+ */
251
+
252
+ $pop() {
253
+ const ret = ArrayMethods.$pop.apply(this, arguments);
254
+
225
255
  _updateParentPopulated(this);
226
256
 
227
257
  return ret;
@@ -239,32 +269,96 @@ const methods = {
239
269
  pull() {
240
270
  const ret = ArrayMethods.pull.apply(this, arguments);
241
271
 
272
+ _updateSubdocIndexes(this);
242
273
  _updateParentPopulated(this);
243
274
 
244
275
  return ret;
245
276
  },
246
277
 
247
278
  /**
248
- * Wraps [`Array#shift`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/unshift) with proper change tracking.
279
+ * Wraps [`Array#shift`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift) with proper change tracking.
249
280
  * @api private
250
281
  */
251
282
 
252
283
  shift() {
253
284
  const ret = ArrayMethods.shift.apply(this, arguments);
254
285
 
286
+ _updateSubdocIndexes(this);
287
+ _updateParentPopulated(this);
288
+
289
+ return ret;
290
+ },
291
+
292
+ /*!
293
+ * ignore
294
+ */
295
+
296
+ $shift() {
297
+ const ret = ArrayMethods.$shift.apply(this, arguments);
298
+
299
+ _updateSubdocIndexes(this);
255
300
  _updateParentPopulated(this);
256
301
 
257
302
  return ret;
258
303
  },
259
304
 
260
305
  /**
261
- * Wraps [`Array#splice`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice) with proper change tracking and casting.
306
+ * Wraps [`Array#splice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice) with proper change tracking and casting.
262
307
  * @api private
263
308
  */
264
309
 
265
310
  splice() {
266
311
  const ret = ArrayMethods.splice.apply(this, arguments);
267
312
 
313
+ _updateSubdocIndexes(this);
314
+ _updateParentPopulated(this);
315
+
316
+ return ret;
317
+ },
318
+
319
+ /**
320
+ * Wraps [`Array#reverse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse)
321
+ * with proper change tracking.
322
+ * @api private
323
+ */
324
+
325
+ reverse() {
326
+ _baseReverse.call(this.__array);
327
+ this._registerAtomic('$set', this);
328
+
329
+ _updateSubdocIndexes(this);
330
+ _updateParentPopulated(this);
331
+
332
+ return this;
333
+ },
334
+
335
+ /**
336
+ * Wraps [`Array#sort`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)
337
+ * with proper change tracking.
338
+ *
339
+ * @param {Function} [compareFunction]
340
+ * @api private
341
+ */
342
+
343
+ sort() {
344
+ const ret = ArrayMethods.sort.apply(this, arguments);
345
+
346
+ _updateSubdocIndexes(this);
347
+ _updateParentPopulated(this);
348
+
349
+ return ret;
350
+ },
351
+
352
+ /**
353
+ * Wraps [`Array#unshift`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift)
354
+ * with proper change tracking.
355
+ * @api private
356
+ */
357
+
358
+ unshift() {
359
+ const ret = ArrayMethods.unshift.apply(this, arguments);
360
+
361
+ _updateSubdocIndexes(this);
268
362
  _updateParentPopulated(this);
269
363
 
270
364
  return ret;
@@ -389,6 +483,26 @@ const methods = {
389
483
 
390
484
  module.exports = methods;
391
485
 
486
+ /*!
487
+ * ignore
488
+ */
489
+
490
+ function _updateSubdocIndexes(arr) {
491
+ const rawArray = utils.isMongooseArray(arr) ? arr.__array : arr;
492
+
493
+ for (let i = 0; i < rawArray.length; ++i) {
494
+ if (typeof rawArray[i]?.$setIndex === 'function') {
495
+ rawArray[i].$setIndex(i);
496
+ }
497
+ }
498
+ }
499
+
500
+ function _shouldReindexAfterPush(args) {
501
+ return args[0] != null &&
502
+ utils.hasUserDefinedProperty(args[0], '$each') &&
503
+ args[0].$position != null;
504
+ }
505
+
392
506
  /**
393
507
  * If this is a document array, each element may contain single
394
508
  * populated paths, so we need to modify the top-level document's
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "9.7.1",
4
+ "version": "9.7.3",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -20,6 +20,7 @@
20
20
  "type": "commonjs",
21
21
  "license": "MIT",
22
22
  "dependencies": {
23
+ "@standard-schema/spec": "^1.1.0",
23
24
  "kareem": "3.3.0",
24
25
  "mongodb": "~7.2",
25
26
  "mpath": "0.9.0",
@@ -43,8 +44,8 @@
43
44
  "eslint-plugin-mocha-no-only": "1.2.0",
44
45
  "express": "5.2.1",
45
46
  "fs-extra": "~11.3.0",
46
- "globals": "^17.4.0",
47
47
  "glob": "^13.0.6",
48
+ "globals": "^17.4.0",
48
49
  "highlight.js": "11.11.1",
49
50
  "linkinator": "7.x",
50
51
  "lodash.isequal": "4.5.0",
@@ -86,7 +87,7 @@
86
87
  "docs:prepare:publish:6x": "git checkout 6.x && git merge 6.x && npm run docs:clean:stable && env DOCS_DEPLOY=true npm run docs:generate && mv ./docs/6.x ./tmp && git checkout gh-pages && npm run docs:copy:tmp:6x",
87
88
  "docs:prepare:publish:7x": "env DOCS_DEPLOY=true npm run docs:generate && git checkout gh-pages && rm -rf ./docs/7.x && mv ./tmp ./docs/7.x",
88
89
  "docs:prepare:publish:8x": "env DOCS_DEPLOY=true npm run docs:generate && git checkout gh-pages && rm -rf ./docs/8.x && mv ./tmp ./docs/8.x",
89
- "docs:check-links": "linkinator http://127.0.0.1:8089 --silent --recurse --skip cdn.carbonads.com --skip m.servedby-buysellads.com --skip \"127\\.0\\.0\\.1:8089\/docs\/\\d+.x\"",
90
+ "docs:check-links": "linkinator http://127.0.0.1:8089 --silent --recurse --skip cdn.carbonads.com --skip m.servedby-buysellads.com --skip \"127\\.0\\.0\\.1:8089/docs/\\d+.x\"",
90
91
  "docs:update-mongodb-links": "node ./scripts/update-mongodb-links.js",
91
92
  "lint": "eslint .",
92
93
  "lint-js": "eslint . --ext .js --ext .cjs",
package/types/models.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  declare module 'mongoose' {
2
2
  import mongodb = require('mongodb');
3
+ import { StandardSchemaV1 as StandardSchemaV1Spec, StandardTypedV1 as StandardTypedV1Spec } from '@standard-schema/spec';
3
4
 
4
5
  export interface DiscriminatorOptions {
5
6
  value?: string | number | ObjectId;
@@ -108,40 +109,8 @@ declare module 'mongoose' {
108
109
  */
109
110
  type pathsToValidate = PathsToValidate;
110
111
 
111
- export namespace StandardSchemaV1 {
112
- export interface Props<Output = unknown> {
113
- readonly version: 1;
114
- readonly vendor: 'mongoose';
115
- readonly validate: (
116
- value: unknown,
117
- options?: Options | undefined
118
- ) => Result<Output> | Promise<Result<Output>>;
119
- }
120
-
121
- export interface Options {
122
- readonly libraryOptions?: Record<string, unknown> | undefined;
123
- }
124
-
125
- export type Result<Output> = SuccessResult<Output> | FailureResult;
126
-
127
- export interface SuccessResult<Output> {
128
- readonly value: Output;
129
- readonly issues?: undefined;
130
- }
131
-
132
- export interface FailureResult {
133
- readonly issues: ReadonlyArray<Issue>;
134
- }
135
-
136
- export interface Issue {
137
- readonly message: string;
138
- readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
139
- }
140
-
141
- export interface PathSegment {
142
- readonly key: PropertyKey;
143
- }
144
- }
112
+ export import StandardTypedV1 = StandardTypedV1Spec;
113
+ export import StandardSchemaV1 = StandardSchemaV1Spec;
145
114
 
146
115
  interface SaveOptions extends
147
116
  SessionOption {
@@ -270,7 +239,7 @@ declare module 'mongoose' {
270
239
  base: Mongoose;
271
240
 
272
241
  /** Standard Schema adapter for validating input with this model's schema. */
273
- readonly '~standard': StandardSchemaV1.Props<TRawDocType>;
242
+ readonly '~standard': StandardSchemaV1.Props<Default__v<Require_id<TRawDocType>, ObtainSchemaGeneric<TSchema, 'TSchemaOptions'>>>;
274
243
 
275
244
  /**
276
245
  * If this is a discriminator model, `baseModelName` is the name of
@@ -684,11 +653,11 @@ declare module 'mongoose' {
684
653
  */
685
654
  useConnection(connection: Connection): this;
686
655
 
687
- /** Casts and validates the given object against this model's schema, passing the given `context` to custom validators. */
688
- validate(): Promise<void>;
689
- validate(obj: any): Promise<void>;
690
- validate(obj: any, pathsOrOptions: PathsToValidate): Promise<void>;
691
- validate(obj: any, pathsOrOptions: { pathsToSkip?: pathsToSkip }): Promise<void>;
656
+ /** Casts and validates the given object against this model's schema, returning the casted-and-validated copy of `obj`, passing the given `context` to custom validators. */
657
+ validate(): Promise<TRawDocType>;
658
+ validate(obj: any): Promise<TRawDocType>;
659
+ validate(obj: any, pathsOrOptions: PathsToValidate): Promise<TRawDocType>;
660
+ validate(obj: any, pathsOrOptions: { pathsToSkip?: pathsToSkip }): Promise<TRawDocType>;
692
661
 
693
662
  /** Watches the underlying collection for changes using [MongoDB change streams](https://www.mongodb.com/docs/manual/changeStreams/). */
694
663
  watch<ResultType extends mongodb.Document = any, ChangeType extends mongodb.ChangeStreamDocument = any>(pipeline?: Array<Record<string, unknown>>, options?: mongodb.ChangeStreamOptions & { hydrate?: boolean }): mongodb.ChangeStream<ResultType, ChangeType>;