mongoose 8.3.1 → 8.3.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
@@ -1053,7 +1053,11 @@ Document.prototype.$set = function $set(path, val, type, options) {
1053
1053
  if (path.$__isNested) {
1054
1054
  path = path.toObject();
1055
1055
  } else {
1056
- path = path._doc;
1056
+ // This ternary is to support gh-7898 (copying virtuals if same schema)
1057
+ // while not breaking gh-10819, which for some reason breaks if we use toObject()
1058
+ path = path.$__schema === this.$__schema
1059
+ ? applyVirtuals(path, { ...path._doc })
1060
+ : path._doc;
1057
1061
  }
1058
1062
  }
1059
1063
  if (path == null) {
@@ -4087,6 +4091,7 @@ function applyVirtuals(self, json, options, toObjectOptions) {
4087
4091
  ? toObjectOptions.aliases
4088
4092
  : true;
4089
4093
 
4094
+ options = options || {};
4090
4095
  let virtualsToApply = null;
4091
4096
  if (Array.isArray(options.virtuals)) {
4092
4097
  virtualsToApply = new Set(options.virtuals);
@@ -4103,7 +4108,6 @@ function applyVirtuals(self, json, options, toObjectOptions) {
4103
4108
  return json;
4104
4109
  }
4105
4110
 
4106
- options = options || {};
4107
4111
  for (i = 0; i < numPaths; ++i) {
4108
4112
  path = paths[i];
4109
4113
 
@@ -4184,7 +4188,12 @@ function applyGetters(self, json, options) {
4184
4188
  for (let ii = 0; ii < plen; ++ii) {
4185
4189
  part = parts[ii];
4186
4190
  v = cur[part];
4187
- if (ii === last) {
4191
+ // If we've reached a non-object part of the branch, continuing would
4192
+ // cause "Cannot create property 'foo' on string 'bar'" error.
4193
+ // Necessary for mongoose-intl plugin re: gh-14446
4194
+ if (branch != null && typeof branch !== 'object') {
4195
+ break;
4196
+ } else if (ii === last) {
4188
4197
  const val = self.$get(path);
4189
4198
  branch[part] = clone(val, options);
4190
4199
  if (Array.isArray(branch[part]) && schema.paths[path].$embeddedSchemaType) {
@@ -20,12 +20,15 @@ function applyEmbeddedDiscriminators(schema, seen = new WeakSet(), overwriteExis
20
20
  continue;
21
21
  }
22
22
  for (const discriminatorKey of schemaType.schema._applyDiscriminators.keys()) {
23
- const discriminatorSchema = schemaType.schema._applyDiscriminators.get(discriminatorKey);
23
+ const {
24
+ schema: discriminatorSchema,
25
+ options
26
+ } = schemaType.schema._applyDiscriminators.get(discriminatorKey);
24
27
  applyEmbeddedDiscriminators(discriminatorSchema, seen);
25
28
  schemaType.discriminator(
26
29
  discriminatorKey,
27
30
  discriminatorSchema,
28
- overwriteExisting ? { overwriteExisting: true } : null
31
+ overwriteExisting ? { ...options, overwriteExisting: true } : options
29
32
  );
30
33
  }
31
34
  schemaType._appliedDiscriminators = true;
@@ -101,8 +101,8 @@ module.exports = function assignVals(o) {
101
101
  valueToSet = numDocs(rawIds[i]);
102
102
  } else if (Array.isArray(o.match)) {
103
103
  valueToSet = Array.isArray(rawIds[i]) ?
104
- rawIds[i].filter(sift(o.match[i])) :
105
- [rawIds[i]].filter(sift(o.match[i]))[0];
104
+ rawIds[i].filter(v => v == null || sift(o.match[i])(v)) :
105
+ [rawIds[i]].filter(v => v == null || sift(o.match[i])(v))[0];
106
106
  } else {
107
107
  valueToSet = rawIds[i];
108
108
  }
package/lib/model.js CHANGED
@@ -4749,7 +4749,7 @@ function _assign(model, vals, mod, assignmentOpts) {
4749
4749
  }
4750
4750
  // flag each as result of population
4751
4751
  if (!lean) {
4752
- val.$__.wasPopulated = val.$__.wasPopulated || true;
4752
+ val.$__.wasPopulated = val.$__.wasPopulated || { value: _val };
4753
4753
  }
4754
4754
  }
4755
4755
  }
package/lib/mongoose.js CHANGED
@@ -637,7 +637,11 @@ Mongoose.prototype._model = function(name, schema, collection, options) {
637
637
 
638
638
  if (schema._applyDiscriminators != null) {
639
639
  for (const disc of schema._applyDiscriminators.keys()) {
640
- model.discriminator(disc, schema._applyDiscriminators.get(disc));
640
+ const {
641
+ schema: discriminatorSchema,
642
+ options
643
+ } = schema._applyDiscriminators.get(disc);
644
+ model.discriminator(disc, discriminatorSchema, options);
641
645
  }
642
646
  }
643
647
 
@@ -447,19 +447,9 @@ SchemaDocumentArray.prototype.cast = function(value, doc, init, prev, options) {
447
447
 
448
448
  const Constructor = getConstructor(this.casterConstructor, rawArray[i]);
449
449
 
450
- // Check if the document has a different schema (re gh-3701)
451
- if (rawArray[i].$__ != null && !(rawArray[i] instanceof Constructor)) {
452
- const spreadDoc = handleSpreadDoc(rawArray[i], true);
453
- if (rawArray[i] !== spreadDoc) {
454
- rawArray[i] = spreadDoc;
455
- } else {
456
- rawArray[i] = rawArray[i].toObject({
457
- transform: false,
458
- // Special case: if different model, but same schema, apply virtuals
459
- // re: gh-7898
460
- virtuals: rawArray[i].schema === Constructor.schema
461
- });
462
- }
450
+ const spreadDoc = handleSpreadDoc(rawArray[i], true);
451
+ if (rawArray[i] !== spreadDoc) {
452
+ rawArray[i] = spreadDoc;
463
453
  }
464
454
 
465
455
  if (rawArray[i] instanceof Subdocument) {
package/lib/schema.js CHANGED
@@ -626,12 +626,18 @@ Schema.prototype.defaultOptions = function(options) {
626
626
  *
627
627
  * @param {String} name the name of the discriminator
628
628
  * @param {Schema} schema the discriminated Schema
629
+ * @param {Object} [options] discriminator options
630
+ * @param {String} [options.value] the string stored in the `discriminatorKey` property. If not specified, Mongoose uses the `name` parameter.
631
+ * @param {Boolean} [options.clone=true] By default, `discriminator()` clones the given `schema`. Set to `false` to skip cloning.
632
+ * @param {Boolean} [options.overwriteModels=false] by default, Mongoose does not allow you to define a discriminator with the same name as another discriminator. Set this to allow overwriting discriminators with the same name.
633
+ * @param {Boolean} [options.mergeHooks=true] By default, Mongoose merges the base schema's hooks with the discriminator schema's hooks. Set this option to `false` to make Mongoose use the discriminator schema's hooks instead.
634
+ * @param {Boolean} [options.mergePlugins=true] By default, Mongoose merges the base schema's plugins with the discriminator schema's plugins. Set this option to `false` to make Mongoose use the discriminator schema's plugins instead.
629
635
  * @return {Schema} the Schema instance
630
636
  * @api public
631
637
  */
632
- Schema.prototype.discriminator = function(name, schema) {
638
+ Schema.prototype.discriminator = function(name, schema, options) {
633
639
  this._applyDiscriminators = this._applyDiscriminators || new Map();
634
- this._applyDiscriminators.set(name, schema);
640
+ this._applyDiscriminators.set(name, { schema, options });
635
641
 
636
642
  return this;
637
643
  };
package/lib/schemaType.js CHANGED
@@ -1542,7 +1542,7 @@ SchemaType.prototype._castRef = function _castRef(value, doc, init) {
1542
1542
  }
1543
1543
 
1544
1544
  if (value.$__ != null) {
1545
- value.$__.wasPopulated = value.$__.wasPopulated || true;
1545
+ value.$__.wasPopulated = value.$__.wasPopulated || { value: value._id };
1546
1546
  return value;
1547
1547
  }
1548
1548
 
@@ -1568,7 +1568,7 @@ SchemaType.prototype._castRef = function _castRef(value, doc, init) {
1568
1568
  !doc.$__.populated[path].options.options ||
1569
1569
  !doc.$__.populated[path].options.options.lean) {
1570
1570
  ret = new pop.options[populateModelSymbol](value);
1571
- ret.$__.wasPopulated = true;
1571
+ ret.$__.wasPopulated = { value: ret._id };
1572
1572
  }
1573
1573
 
1574
1574
  return ret;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "8.3.1",
4
+ "version": "8.3.2",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
package/types/index.d.ts CHANGED
@@ -431,7 +431,7 @@ declare module 'mongoose' {
431
431
  fn: (
432
432
  this: T,
433
433
  next: (err?: CallbackError) => void,
434
- ops: Array<mongodb.AnyBulkWriteOperation<any> & MongooseBulkWritePerWriteOptions>,
434
+ ops: Array<AnyBulkWriteOperation<any>>,
435
435
  options?: mongodb.BulkWriteOptions & MongooseBulkWriteOptions
436
436
  ) => void | Promise<void>
437
437
  ): this;
package/types/models.d.ts CHANGED
@@ -23,13 +23,21 @@ declare module 'mongoose' {
23
23
  ): U;
24
24
  }
25
25
 
26
- interface MongooseBulkWriteOptions {
26
+ interface MongooseBulkWriteOptions extends mongodb.BulkWriteOptions {
27
+ session?: ClientSession;
27
28
  skipValidation?: boolean;
28
29
  throwOnValidationError?: boolean;
29
- timestamps?: boolean;
30
30
  strict?: boolean | 'throw';
31
31
  }
32
32
 
33
+ interface MongooseBulkSaveOptions extends mongodb.BulkWriteOptions {
34
+ timestamps?: boolean;
35
+ session?: ClientSession;
36
+ }
37
+
38
+ /**
39
+ * @deprecated use AnyBulkWriteOperation instead
40
+ */
33
41
  interface MongooseBulkWritePerWriteOptions {
34
42
  timestamps?: boolean;
35
43
  strict?: boolean | 'throw';
@@ -200,6 +208,8 @@ declare module 'mongoose' {
200
208
  hint?: mongodb.Hint;
201
209
  /** When true, creates a new document if no document matches the query. */
202
210
  upsert?: boolean;
211
+ /** When false, do not add timestamps. */
212
+ timestamps?: boolean;
203
213
  }
204
214
 
205
215
  export interface UpdateManyModel<TSchema = AnyObject> {
@@ -215,6 +225,8 @@ declare module 'mongoose' {
215
225
  hint?: mongodb.Hint;
216
226
  /** When true, creates a new document if no document matches the query. */
217
227
  upsert?: boolean;
228
+ /** When false, do not add timestamps. */
229
+ timestamps?: boolean;
218
230
  }
219
231
 
220
232
  export interface DeleteOneModel<TSchema = AnyObject> {
@@ -281,11 +293,11 @@ declare module 'mongoose' {
281
293
  */
282
294
  bulkWrite<DocContents = TRawDocType>(
283
295
  writes: Array<AnyBulkWriteOperation<DocContents extends Document ? any : (DocContents extends {} ? DocContents : any)>>,
284
- options: mongodb.BulkWriteOptions & MongooseBulkWriteOptions & { ordered: false }
296
+ options: MongooseBulkWriteOptions & { ordered: false }
285
297
  ): Promise<mongodb.BulkWriteResult & { mongoose?: { validationErrors: Error[] } }>;
286
298
  bulkWrite<DocContents = TRawDocType>(
287
299
  writes: Array<AnyBulkWriteOperation<DocContents extends Document ? any : (DocContents extends {} ? DocContents : any)>>,
288
- options?: mongodb.BulkWriteOptions & MongooseBulkWriteOptions
300
+ options?: MongooseBulkWriteOptions
289
301
  ): Promise<mongodb.BulkWriteResult>;
290
302
 
291
303
  /**
@@ -293,7 +305,7 @@ declare module 'mongoose' {
293
305
  * sending multiple `save()` calls because with `bulkSave()` there is only one
294
306
  * network round trip to the MongoDB server.
295
307
  */
296
- bulkSave(documents: Array<Document>, options?: mongodb.BulkWriteOptions & { timestamps?: boolean }): Promise<mongodb.BulkWriteResult>;
308
+ bulkSave(documents: Array<Document>, options?: MongooseBulkSaveOptions): Promise<mongodb.BulkWriteResult>;
297
309
 
298
310
  /** Collection the model uses. */
299
311
  collection: Collection;
package/types/query.d.ts CHANGED
@@ -1,24 +1,7 @@
1
1
  declare module 'mongoose' {
2
2
  import mongodb = require('mongodb');
3
3
 
4
- type StringQueryTypeCasting = string | RegExp;
5
- type ObjectIdQueryTypeCasting = Types.ObjectId | string;
6
- type UUIDQueryTypeCasting = Types.UUID | string;
7
-
8
- type QueryTypeCasting<T> = T extends string
9
- ? StringQueryTypeCasting
10
- : T extends Types.ObjectId
11
- ? ObjectIdQueryTypeCasting
12
- : T extends Types.UUID
13
- ? UUIDQueryTypeCasting
14
- : T | any;
15
-
16
- export type ApplyBasicQueryCasting<T> = T | T[] | (T extends (infer U)[] ? QueryTypeCasting<U> : T);
17
- export type Condition<T> = ApplyBasicQueryCasting<QueryTypeCasting<T>> | QuerySelector<ApplyBasicQueryCasting<QueryTypeCasting<T>>>;
18
-
19
- type _FilterQuery<T> = {
20
- [P in keyof T]?: Condition<T[P]>;
21
- } & RootQuerySelector<T>;
4
+ export type Condition<T> = T | QuerySelector<T | any> | any;
22
5
 
23
6
  /**
24
7
  * Filter query to select the documents that match the query
@@ -27,7 +10,9 @@ declare module 'mongoose' {
27
10
  * { age: { $gte: 30 } }
28
11
  * ```
29
12
  */
30
- type FilterQuery<T> = _FilterQuery<T>;
13
+ type FilterQuery<T> = {
14
+ [P in keyof T]?: Condition<T[P]>;
15
+ } & RootQuerySelector<T>;
31
16
 
32
17
  type MongooseBaseQueryOptionKeys =
33
18
  | 'context'
package/types/types.d.ts CHANGED
@@ -60,7 +60,7 @@ declare module 'mongoose' {
60
60
 
61
61
  class Decimal128 extends mongodb.Decimal128 { }
62
62
 
63
- class DocumentArray<T> extends Types.Array<T extends Types.Subdocument ? T : Types.Subdocument<InferId<T>> & T> {
63
+ class DocumentArray<T> extends Types.Array<T extends Types.Subdocument ? T : Types.Subdocument<InferId<T>, any, T> & T> {
64
64
  /** DocumentArray constructor */
65
65
  constructor(values: AnyObject[]);
66
66
 
@@ -83,7 +83,7 @@ declare module 'mongoose' {
83
83
  class ObjectId extends mongodb.ObjectId {
84
84
  }
85
85
 
86
- class Subdocument<IdType = any> extends Document<IdType> {
86
+ class Subdocument<IdType = any, TQueryHelpers = any, DocType = any> extends Document<IdType, TQueryHelpers, DocType> {
87
87
  $isSingleNested: true;
88
88
 
89
89
  /** Returns the top level document of this sub-document. */