mongoose 8.7.1 → 8.7.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.
@@ -25,11 +25,21 @@ module.exports = function cleanModifiedSubpaths(doc, path, options) {
25
25
  ++deleted;
26
26
 
27
27
  if (doc.$isSubdocument) {
28
- const owner = doc.ownerDocument();
29
- const fullPath = doc.$__fullPath(modifiedPath);
30
- owner.$__.activePaths.clearPath(fullPath);
28
+ cleanParent(doc, modifiedPath);
31
29
  }
32
30
  }
33
31
  }
34
32
  return deleted;
35
33
  };
34
+
35
+ function cleanParent(doc, path, seen = new Set()) {
36
+ if (seen.has(doc)) {
37
+ throw new Error('Infinite subdocument loop: subdoc with _id ' + doc._id + ' is a parent of itself');
38
+ }
39
+ const parent = doc.$parent();
40
+ const newPath = doc.$__pathRelativeToParent(void 0, false) + '.' + path;
41
+ parent.$__.activePaths.clearPath(newPath);
42
+ if (parent.$isSubdocument) {
43
+ cleanParent(parent, newPath, seen);
44
+ }
45
+ }
@@ -478,9 +478,10 @@ function addModelNamesToMap(model, map, available, modelNames, options, data, re
478
478
  return;
479
479
  }
480
480
 
481
- let k = modelNames.length;
481
+ const flatModelNames = utils.array.flatten(modelNames);
482
+ let k = flatModelNames.length;
482
483
  while (k--) {
483
- let modelName = modelNames[k];
484
+ let modelName = flatModelNames[k];
484
485
  if (modelName == null) {
485
486
  continue;
486
487
  }
@@ -503,11 +504,10 @@ function addModelNamesToMap(model, map, available, modelNames, options, data, re
503
504
  }
504
505
 
505
506
  let ids = ret;
506
- const flat = Array.isArray(ret) ? utils.array.flatten(ret) : [];
507
507
 
508
508
  const modelNamesForRefPath = data.modelNamesInOrder ? data.modelNamesInOrder : modelNames;
509
- if (data.isRefPath && Array.isArray(ret) && flat.length === modelNamesForRefPath.length) {
510
- ids = flat.filter((val, i) => modelNamesForRefPath[i] === modelName);
509
+ if (data.isRefPath && Array.isArray(ret) && ret.length === modelNamesForRefPath.length) {
510
+ ids = matchIdsToRefPaths(ret, modelNamesForRefPath, modelName);
511
511
  }
512
512
 
513
513
  const perDocumentLimit = options.perDocumentLimit == null ?
@@ -569,6 +569,20 @@ function _getModelFromConn(conn, modelName) {
569
569
  return conn.model(modelName);
570
570
  }
571
571
 
572
+ function matchIdsToRefPaths(ids, refPaths, refPathToFind) {
573
+ if (!Array.isArray(refPaths)) {
574
+ return refPaths === refPathToFind
575
+ ? Array.isArray(ids)
576
+ ? utils.array.flatten(ids)
577
+ : [ids]
578
+ : [];
579
+ }
580
+ if (Array.isArray(ids) && Array.isArray(refPaths)) {
581
+ return ids.flatMap((id, index) => matchIdsToRefPaths(id, refPaths[index], refPathToFind));
582
+ }
583
+ return [];
584
+ }
585
+
572
586
  /*!
573
587
  * ignore
574
588
  */
@@ -62,7 +62,5 @@ module.exports = function modelNamesFromRefPath(refPath, doc, populatedPath, mod
62
62
  modelNames = Array.isArray(refValue) ? refValue : [refValue];
63
63
  }
64
64
 
65
- modelNames = utils.array.flatten(modelNames);
66
-
67
65
  return modelNames;
68
66
  };
package/lib/model.js CHANGED
@@ -3771,7 +3771,7 @@ Model.hydrate = function(obj, projection, options) {
3771
3771
  * const res = await Person.updateMany({ name: /Stark$/ }, { isDeleted: true });
3772
3772
  * res.matchedCount; // Number of documents matched
3773
3773
  * res.modifiedCount; // Number of documents modified
3774
- * res.acknowledged; // Boolean indicating everything went smoothly.
3774
+ * res.acknowledged; // Boolean indicating the MongoDB server received the operation. This may be false if Mongoose did not send an update to the server because the update was empty.
3775
3775
  * res.upsertedId; // null or an id containing a document that had to be upserted.
3776
3776
  * res.upsertedCount; // Number indicating how many documents had to be upserted. Will either be 0 or 1.
3777
3777
  *
@@ -3811,7 +3811,7 @@ Model.updateMany = function updateMany(conditions, doc, options) {
3811
3811
  * const res = await Person.updateOne({ name: 'Jean-Luc Picard' }, { ship: 'USS Enterprise' });
3812
3812
  * res.matchedCount; // Number of documents matched
3813
3813
  * res.modifiedCount; // Number of documents modified
3814
- * res.acknowledged; // Boolean indicating everything went smoothly.
3814
+ * res.acknowledged; // Boolean indicating the MongoDB server received the operation. This may be false if Mongoose did not send an update to the server because the update was empty.
3815
3815
  * res.upsertedId; // null or an id containing a document that had to be upserted.
3816
3816
  * res.upsertedCount; // Number indicating how many documents had to be upserted. Will either be 0 or 1.
3817
3817
  *
@@ -3849,7 +3849,7 @@ Model.updateOne = function updateOne(conditions, doc, options) {
3849
3849
  * const res = await Person.replaceOne({ _id: 24601 }, { name: 'Jean Valjean' });
3850
3850
  * res.matchedCount; // Number of documents matched
3851
3851
  * res.modifiedCount; // Number of documents modified
3852
- * res.acknowledged; // Boolean indicating everything went smoothly.
3852
+ * res.acknowledged; // Boolean indicating the MongoDB server received the operation.
3853
3853
  * res.upsertedId; // null or an id containing a document that had to be upserted.
3854
3854
  * res.upsertedCount; // Number indicating how many documents had to be upserted. Will either be 0 or 1.
3855
3855
  *
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "8.7.1",
4
+ "version": "8.7.2",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -92,7 +92,7 @@
92
92
  "lint": "eslint .",
93
93
  "lint-js": "eslint . --ext .js --ext .cjs",
94
94
  "lint-ts": "eslint . --ext .ts",
95
- "lint-md": "markdownlint-cli2 \"**/*.md\"",
95
+ "lint-md": "markdownlint-cli2 \"**/*.md\" \"#node_modules\" \"#benchmarks\"",
96
96
  "build-browser": "(rm ./dist/* || true) && node ./scripts/build-browser.js",
97
97
  "prepublishOnly": "npm run build-browser",
98
98
  "release": "git pull && git push origin master --tags && npm publish",
package/types/index.d.ts CHANGED
@@ -706,6 +706,18 @@ declare module 'mongoose' {
706
706
  [K in keyof T]: FlattenProperty<T[K]>;
707
707
  };
708
708
 
709
+ export type BufferToBinary<T> = T extends TreatAsPrimitives ? T : T extends Record<string, any> ? {
710
+ [K in keyof T]: T[K] extends Buffer
711
+ ? mongodb.Binary
712
+ : T[K] extends (Buffer | null | undefined)
713
+ ? mongodb.Binary | null | undefined
714
+ : T[K] extends Types.DocumentArray<infer ItemType>
715
+ ? Types.DocumentArray<BufferToBinary<ItemType>>
716
+ : T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
717
+ ? HydratedSingleSubdocument<SubdocType>
718
+ : BufferToBinary<T[K]>;
719
+ } : T;
720
+
709
721
  /**
710
722
  * Separate type is needed for properties of union type (for example, Types.DocumentArray | undefined) to apply conditional check to each member of it
711
723
  * https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types
@@ -716,7 +728,7 @@ declare module 'mongoose' {
716
728
  ? Types.DocumentArray<FlattenMaps<ItemType>> : FlattenMaps<T>;
717
729
 
718
730
  export type actualPrimitives = string | boolean | number | bigint | symbol | null | undefined;
719
- export type TreatAsPrimitives = actualPrimitives | NativeDate | RegExp | symbol | Error | BigInt | Types.ObjectId | Buffer | Function;
731
+ export type TreatAsPrimitives = actualPrimitives | NativeDate | RegExp | symbol | Error | BigInt | Types.ObjectId | Buffer | Function | mongodb.Binary;
720
732
 
721
733
  export type SchemaDefinitionType<T> = T extends Document ? Omit<T, Exclude<keyof Document, '_id' | 'id' | '__v'>> : T;
722
734
 
@@ -183,8 +183,16 @@ type TypeHint<T> = T extends { __typehint: infer U } ? U: never;
183
183
  * @param {TypeKey} TypeKey A generic refers to document definition.
184
184
  */
185
185
  type ObtainDocumentPathType<PathValueType, TypeKey extends string = DefaultTypeKey> = ResolvePathType<
186
- PathValueType extends PathWithTypePropertyBaseType<TypeKey> ? PathValueType[TypeKey] : PathValueType,
187
- PathValueType extends PathWithTypePropertyBaseType<TypeKey> ? Omit<PathValueType, TypeKey> : {},
186
+ PathValueType extends PathWithTypePropertyBaseType<TypeKey>
187
+ ? PathValueType[TypeKey] extends PathWithTypePropertyBaseType<TypeKey>
188
+ ? PathValueType
189
+ : PathValueType[TypeKey]
190
+ : PathValueType,
191
+ PathValueType extends PathWithTypePropertyBaseType<TypeKey>
192
+ ? PathValueType[TypeKey] extends PathWithTypePropertyBaseType<TypeKey>
193
+ ? {}
194
+ : Omit<PathValueType, TypeKey>
195
+ : {},
188
196
  TypeKey,
189
197
  TypeHint<PathValueType>
190
198
  >;
package/types/models.d.ts CHANGED
@@ -72,6 +72,8 @@ declare module 'mongoose' {
72
72
  };
73
73
 
74
74
  type UpdateWriteOpResult = mongodb.UpdateResult;
75
+ type UpdateResult = mongodb.UpdateResult;
76
+ type DeleteResult = mongodb.DeleteResult;
75
77
 
76
78
  interface MapReduceOptions<T, K, R> {
77
79
  map: Function | string;
package/types/query.d.ts CHANGED
@@ -211,7 +211,7 @@ declare module 'mongoose' {
211
211
  type QueryOpThatReturnsDocument = 'find' | 'findOne' | 'findOneAndUpdate' | 'findOneAndReplace' | 'findOneAndDelete';
212
212
 
213
213
  type GetLeanResultType<RawDocType, ResultType, QueryOp> = QueryOp extends QueryOpThatReturnsDocument
214
- ? (ResultType extends any[] ? Require_id<FlattenMaps<RawDocType>>[] : Require_id<FlattenMaps<RawDocType>>)
214
+ ? (ResultType extends any[] ? Require_id<BufferToBinary<FlattenMaps<RawDocType>>>[] : Require_id<BufferToBinary<FlattenMaps<RawDocType>>>)
215
215
  : ResultType;
216
216
 
217
217
  type MergePopulatePaths<RawDocType, ResultType, QueryOp, Paths, TQueryHelpers, TInstanceMethods = Record<string, never>> = QueryOp extends QueryOpThatReturnsDocument