mongoose 6.8.2 → 6.8.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.
@@ -6,6 +6,8 @@ const utils = require('../../utils');
6
6
 
7
7
  module.exports = assignRawDocsToIdStructure;
8
8
 
9
+ const kHasArray = Symbol('assignRawDocsToIdStructure.hasArray');
10
+
9
11
  /**
10
12
  * Assign `vals` returned by mongo query to the `rawIds`
11
13
  * structure returned from utils.getVals() honoring
@@ -43,7 +45,16 @@ function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, re
43
45
 
44
46
  let i = 0;
45
47
  const len = rawIds.length;
46
- const hasResultArrays = Object.values(resultOrder).find(o => Array.isArray(o));
48
+
49
+ if (sorting && recursed && options[kHasArray] === undefined) {
50
+ options[kHasArray] = false;
51
+ for (const key in resultOrder) {
52
+ if (Array.isArray(resultOrder[key])) {
53
+ options[kHasArray] = true;
54
+ break;
55
+ }
56
+ }
57
+ }
47
58
 
48
59
  for (i = 0; i < len; ++i) {
49
60
  id = rawIds[i];
@@ -55,7 +66,7 @@ function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, re
55
66
  continue;
56
67
  }
57
68
 
58
- if (id === null && !sorting) {
69
+ if (id === null && sorting === false) {
59
70
  // keep nulls for findOne unless sorting, which always
60
71
  // removes them (backward compat)
61
72
  newOrder.push(id);
@@ -79,7 +90,7 @@ function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, re
79
90
  if (doc) {
80
91
  if (sorting) {
81
92
  const _resultOrder = resultOrder[sid];
82
- if (hasResultArrays) {
93
+ if (options[kHasArray]) {
83
94
  // If result arrays, rely on the MongoDB server response for ordering
84
95
  newOrder.push(doc);
85
96
  } else {
package/lib/model.js CHANGED
@@ -3411,7 +3411,8 @@ Model.$__insertMany = function(arr, options, callback) {
3411
3411
  }
3412
3412
 
3413
3413
  const validationErrors = [];
3414
- const toExecute = arr.map(doc =>
3414
+ const validationErrorsToOriginalOrder = new Map();
3415
+ const toExecute = arr.map((doc, index) =>
3415
3416
  callback => {
3416
3417
  if (!(doc instanceof _this)) {
3417
3418
  try {
@@ -3437,6 +3438,7 @@ Model.$__insertMany = function(arr, options, callback) {
3437
3438
  // failed. It's up to the next function to filter out all failed models
3438
3439
  if (ordered === false) {
3439
3440
  validationErrors.push(error);
3441
+ validationErrorsToOriginalOrder.set(error, index);
3440
3442
  return callback(null, null);
3441
3443
  }
3442
3444
  return callback(error);
@@ -3450,14 +3452,38 @@ Model.$__insertMany = function(arr, options, callback) {
3450
3452
  callback(error, null);
3451
3453
  return;
3452
3454
  }
3455
+
3456
+ const originalDocIndex = new Map();
3457
+ const validDocIndexToOriginalIndex = new Map();
3458
+ for (let i = 0; i < docs.length; ++i) {
3459
+ originalDocIndex.set(docs[i], i);
3460
+ }
3461
+
3453
3462
  // We filter all failed pre-validations by removing nulls
3454
3463
  const docAttributes = docs.filter(function(doc) {
3455
3464
  return doc != null;
3456
3465
  });
3466
+ for (let i = 0; i < docAttributes.length; ++i) {
3467
+ validDocIndexToOriginalIndex.set(i, originalDocIndex.get(docAttributes[i]));
3468
+ }
3469
+
3470
+ // Make sure validation errors are in the same order as the
3471
+ // original documents, so if both doc1 and doc2 both fail validation,
3472
+ // `Model.insertMany([doc1, doc2])` will always have doc1's validation
3473
+ // error before doc2's. Re: gh-12791.
3474
+ if (validationErrors.length > 0) {
3475
+ validationErrors.sort((err1, err2) => {
3476
+ return validationErrorsToOriginalOrder.get(err1) - validationErrorsToOriginalOrder.get(err2);
3477
+ });
3478
+ }
3479
+
3457
3480
  // Quickly escape while there aren't any valid docAttributes
3458
3481
  if (docAttributes.length === 0) {
3459
3482
  if (rawResult) {
3460
3483
  const res = {
3484
+ acknowledged: true,
3485
+ insertedCount: 0,
3486
+ insertedIds: {},
3461
3487
  mongoose: {
3462
3488
  validationErrors: validationErrors
3463
3489
  }
@@ -3490,6 +3516,13 @@ Model.$__insertMany = function(arr, options, callback) {
3490
3516
  // `insertedDocs` is a Mongoose-specific property
3491
3517
  const erroredIndexes = new Set((error && error.writeErrors || []).map(err => err.index));
3492
3518
 
3519
+ for (let i = 0; i < error.writeErrors.length; ++i) {
3520
+ error.writeErrors[i] = {
3521
+ ...error.writeErrors[i],
3522
+ index: validDocIndexToOriginalIndex.get(error.writeErrors[i].index)
3523
+ };
3524
+ }
3525
+
3493
3526
  let firstErroredIndex = -1;
3494
3527
  error.insertedDocs = docAttributes.
3495
3528
  filter((doc, i) => {
@@ -3513,6 +3546,12 @@ Model.$__insertMany = function(arr, options, callback) {
3513
3546
  return doc;
3514
3547
  });
3515
3548
 
3549
+ if (rawResult && ordered === false) {
3550
+ error.mongoose = {
3551
+ validationErrors: validationErrors
3552
+ };
3553
+ }
3554
+
3516
3555
  callback(error, null);
3517
3556
  return;
3518
3557
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "6.8.2",
4
+ "version": "6.8.3",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -20,7 +20,7 @@
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
22
  "bson": "^4.7.0",
23
- "kareem": "2.5.0",
23
+ "kareem": "2.5.1",
24
24
  "mongodb": "4.12.1",
25
25
  "mpath": "0.9.0",
26
26
  "mquery": "4.0.3",
@@ -28,10 +28,10 @@
28
28
  "sift": "16.0.1"
29
29
  },
30
30
  "devDependencies": {
31
- "@babel/core": "7.20.5",
31
+ "@babel/core": "7.20.7",
32
32
  "@babel/preset-env": "7.20.2",
33
- "@typescript-eslint/eslint-plugin": "5.45.0",
34
- "@typescript-eslint/parser": "5.45.0",
33
+ "@typescript-eslint/eslint-plugin": "5.47.1",
34
+ "@typescript-eslint/parser": "5.47.1",
35
35
  "acquit": "1.2.1",
36
36
  "acquit-ignore": "0.2.0",
37
37
  "acquit-require": "0.1.1",
@@ -44,22 +44,22 @@
44
44
  "cheerio": "1.0.0-rc.12",
45
45
  "crypto-browserify": "3.12.0",
46
46
  "dox": "1.0.0",
47
- "eslint": "8.28.0",
47
+ "eslint": "8.31.0",
48
48
  "eslint-plugin-mocha-no-only": "1.1.1",
49
49
  "express": "^4.18.1",
50
50
  "highlight.js": "11.7.0",
51
51
  "lodash.isequal": "4.5.0",
52
52
  "lodash.isequalwith": "4.4.0",
53
- "marked": "4.2.3",
53
+ "marked": "4.2.5",
54
54
  "mkdirp": "^1.0.4",
55
- "mocha": "10.1.0",
55
+ "mocha": "10.2.0",
56
56
  "moment": "2.x",
57
- "mongodb-memory-server": "8.10.1",
57
+ "mongodb-memory-server": "8.10.2",
58
58
  "ncp": "^2.0.0",
59
59
  "nyc": "15.1.0",
60
60
  "pug": "3.0.2",
61
61
  "q": "1.5.1",
62
- "sinon": "15.0.0",
62
+ "sinon": "15.0.1",
63
63
  "stream-browserify": "3.0.0",
64
64
  "tsd": "0.25.0",
65
65
  "typescript": "4.9.4",
@@ -166,6 +166,11 @@ declare module 'mongoose' {
166
166
  */
167
167
  model(model: Model<any>): this;
168
168
 
169
+ /**
170
+ * Returns the current model bound to this aggregate object
171
+ */
172
+ model(): Model<any>;
173
+
169
174
  /**
170
175
  * Append a new $near operator to this aggregation pipeline
171
176
  * @param arg $near operator contents
package/types/index.d.ts CHANGED
@@ -353,7 +353,7 @@ declare module 'mongoose' {
353
353
  statics: { [F in keyof TStaticMethods]: TStaticMethods[F] } & { [name: string]: (this: M, ...args: any[]) => any };
354
354
 
355
355
  /** Creates a virtual type with the given name. */
356
- virtual<T = HydratedDocument<DocType, TInstanceMethods>>(
356
+ virtual<T = HydratedDocument<DocType, TInstanceMethods, TVirtuals>>(
357
357
  name: keyof TVirtuals | string,
358
358
  options?: VirtualTypeOptions<T, DocType>
359
359
  ): VirtualType<T>;
@@ -60,12 +60,18 @@ declare module 'mongoose' {
60
60
  }[alias]
61
61
  : unknown;
62
62
 
63
- type ResolveSchemaOptions<T> = Omit<MergeType<DefaultSchemaOptions, T>, 'statics' | 'methods' | 'query' | 'virtuals'>;
63
+ // Without Omit, this gives us a "Type parameter 'TSchemaOptions' has a circular constraint."
64
+ type ResolveSchemaOptions<T> = Omit<MergeType<DefaultSchemaOptions, T>, 'fakepropertyname'>;
64
65
 
65
66
  type ApplySchemaOptions<T, O = DefaultSchemaOptions> = ResolveTimestamps<T, O>;
66
67
 
67
68
  type ResolveTimestamps<T, O> = O extends { timestamps: true }
68
- ? { createdAt: NativeDate; updatedAt: NativeDate; } & T
69
+ // For some reason, TypeScript sets all the document properties to unknown
70
+ // if we use methods, statics, or virtuals. So avoid inferring timestamps
71
+ // if any of these are set for now. See gh-12807
72
+ ? O extends { methods: any } | { statics: any } | { virtuals: any }
73
+ ? T
74
+ : { createdAt: NativeDate; updatedAt: NativeDate; } & T
69
75
  : T;
70
76
  }
71
77
 
@@ -162,7 +168,7 @@ type ObtainDocumentPathType<PathValueType, TypeKey extends string = DefaultTypeK
162
168
  * @param {T} T A generic refers to string path enums.
163
169
  * @returns Path enum values type as literal strings or string.
164
170
  */
165
- type PathEnumOrString<T extends SchemaTypeOptions<string>['enum']> = T extends (infer E)[] ? E : T extends { values: any } ? PathEnumOrString<T['values']> : string;
171
+ type PathEnumOrString<T extends SchemaTypeOptions<string>['enum']> = T extends ReadonlyArray<infer E> ? E : T extends { values: any } ? PathEnumOrString<T['values']> : string;
166
172
 
167
173
  /**
168
174
  * @summary Resolve path type by returning the corresponding type.