mongoose 6.7.1 → 6.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/lib/document.js CHANGED
@@ -220,6 +220,17 @@ function Document(obj, fields, skipId, options) {
220
220
  * const user = await User.findOne({ name: 'John Smith' });
221
221
  * user.$isNew; // false
222
222
  *
223
+ * Mongoose sets `$isNew` to `false` immediately after `save()` succeeds.
224
+ * That means Mongoose sets `$isNew` to false **before** `post('save')` hooks run.
225
+ * In `post('save')` hooks, `$isNew` will be `false` if `save()` succeeded.
226
+ *
227
+ * #### Example:
228
+ *
229
+ * userSchema.post('save', function() {
230
+ * this.$isNew; // false
231
+ * });
232
+ * await User.create({ name: 'John Smith' });
233
+ *
223
234
  * For subdocuments, `$isNew` is true if either the parent has `$isNew` set,
224
235
  * or if you create a new subdocument.
225
236
  *
@@ -1468,13 +1479,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
1468
1479
  const doc = this.$isSubdocument ? this.ownerDocument() : this;
1469
1480
  savedState = doc.$__.savedState;
1470
1481
  savedStatePath = this.$isSubdocument ? this.$__.fullPath + '.' + path : path;
1471
- if (savedState != null) {
1472
- const firstDot = savedStatePath.indexOf('.');
1473
- const topLevelPath = firstDot === -1 ? savedStatePath : savedStatePath.slice(0, firstDot);
1474
- if (!savedState.hasOwnProperty(topLevelPath)) {
1475
- savedState[topLevelPath] = utils.clone(doc.$__getValue(topLevelPath));
1476
- }
1477
- }
1482
+ doc.$__saveInitialState(savedStatePath);
1478
1483
  }
1479
1484
 
1480
1485
  this.$__set(pathToMark, path, options, constructing, parts, schema, val, priorVal);
@@ -1583,6 +1588,10 @@ Document.prototype.$__shouldModify = function(pathToMark, path, options, constru
1583
1588
  if (this.$isNew) {
1584
1589
  return true;
1585
1590
  }
1591
+ // Is path already modified? If so, always modify. We may unmark modified later.
1592
+ if (path in this.$__.activePaths.getStatePaths('modify')) {
1593
+ return true;
1594
+ }
1586
1595
 
1587
1596
  // Re: the note about gh-7196, `val` is the raw value without casting or
1588
1597
  // setters if the full path is under a single nested subdoc because we don't
@@ -1780,11 +1789,10 @@ Document.prototype.$inc = function $inc(path, val) {
1780
1789
 
1781
1790
  const currentValue = this.$__getValue(path) || 0;
1782
1791
 
1783
- this.$__setValue(path, currentValue + val);
1784
-
1785
1792
  this.$__.primitiveAtomics = this.$__.primitiveAtomics || {};
1786
1793
  this.$__.primitiveAtomics[path] = { $inc: val };
1787
1794
  this.markModified(path);
1795
+ this.$__setValue(path, currentValue + val);
1788
1796
 
1789
1797
  return this;
1790
1798
  };
@@ -1927,6 +1935,8 @@ Document.prototype.$__path = function(path) {
1927
1935
  */
1928
1936
 
1929
1937
  Document.prototype.markModified = function(path, scope) {
1938
+ this.$__saveInitialState(path);
1939
+
1930
1940
  this.$__.activePaths.modify(path);
1931
1941
  if (scope != null && !this.$isSubdocument) {
1932
1942
  this.$__.pathsToScopes = this.$__pathsToScopes || {};
@@ -1934,6 +1944,22 @@ Document.prototype.markModified = function(path, scope) {
1934
1944
  }
1935
1945
  };
1936
1946
 
1947
+ /*!
1948
+ * ignore
1949
+ */
1950
+
1951
+ Document.prototype.$__saveInitialState = function $__saveInitialState(path) {
1952
+ const savedState = this.$__.savedState;
1953
+ const savedStatePath = path;
1954
+ if (savedState != null) {
1955
+ const firstDot = savedStatePath.indexOf('.');
1956
+ const topLevelPath = firstDot === -1 ? savedStatePath : savedStatePath.slice(0, firstDot);
1957
+ if (!savedState.hasOwnProperty(topLevelPath)) {
1958
+ savedState[topLevelPath] = utils.clone(this.$__getValue(topLevelPath));
1959
+ }
1960
+ }
1961
+ };
1962
+
1937
1963
  /**
1938
1964
  * Clears the modified state on the specified path.
1939
1965
  *
@@ -3379,6 +3405,7 @@ Document.prototype.$__dirty = function() {
3379
3405
  schema: _this.$__path(path)
3380
3406
  };
3381
3407
  });
3408
+
3382
3409
  // gh-2558: if we had to set a default and the value is not undefined,
3383
3410
  // we have to save as well
3384
3411
  all = all.concat(this.$__.activePaths.map('default', function(path) {
@@ -184,8 +184,9 @@ module.exports = function discriminator(model, name, schema, tiedValue, applyPlu
184
184
  if (mergeHooks) {
185
185
  schema.s.hooks = model.schema.s.hooks.merge(schema.s.hooks);
186
186
  }
187
-
188
- schema.plugins = Array.prototype.slice.call(baseSchema.plugins);
187
+ if (applyPlugins) {
188
+ schema.plugins = Array.prototype.slice.call(baseSchema.plugins);
189
+ }
189
190
  schema.callQueue = baseSchema.callQueue.concat(schema.callQueue);
190
191
  delete schema._requiredpaths; // reset just in case Schema#requiredPaths() was called on either schema
191
192
  }
@@ -28,7 +28,7 @@ module.exports = function setupTimestamps(schema, timestamps) {
28
28
  schema.$timestamps = { createdAt: createdAt, updatedAt: updatedAt };
29
29
 
30
30
  if (createdAt && !schema.paths[createdAt]) {
31
- const baseImmutableCreatedAt = schema.base.get('timestamps.createdAt.immutable');
31
+ const baseImmutableCreatedAt = schema.base != null ? schema.base.get('timestamps.createdAt.immutable') : null;
32
32
  const immutable = baseImmutableCreatedAt != null ? baseImmutableCreatedAt : true;
33
33
  schemaAdditions[createdAt] = { [schema.options.typeKey || 'type']: Date, immutable };
34
34
  }
package/lib/index.js CHANGED
@@ -205,7 +205,6 @@ Mongoose.prototype.setDriver = function setDriver(driver) {
205
205
  * - 'returnOriginal': If `false`, changes the default `returnOriginal` option to `findOneAndUpdate()`, `findByIdAndUpdate`, and `findOneAndReplace()` to false. This is equivalent to setting the `new` option to `true` for `findOneAndX()` calls by default. Read our [`findOneAndUpdate()` tutorial](/docs/tutorials/findoneandupdate.html) for more information.
206
206
  * - 'bufferCommands': enable/disable mongoose's buffering mechanism for all connections and models
207
207
  * - 'cloneSchemas': `false` by default. Set to `true` to `clone()` all schemas before compiling into a model.
208
- * - 'debug': If `true`, prints the operations mongoose sends to MongoDB to the console. If a writable stream is passed, it will log to that stream, without colorization. If a callback function is passed, it will receive the collection name, the method name, then all arugments passed to the method. For example, if you wanted to replicate the default logging, you could output from the callback `Mongoose: ${collectionName}.${methodName}(${methodArgs.join(', ')})`.
209
208
  * - 'timestamps.createdAt.immutable': `true` by default. If `false`, it will change the `createdAt` field to be [`immutable: false`](https://mongoosejs.com/docs/api/schematype.html#schematype_SchemaType-immutable) which means you can update the `createdAt`
210
209
  * - 'maxTimeMS': If set, attaches [maxTimeMS](https://docs.mongodb.com/manual/reference/operator/meta/maxTimeMS/) to every query
211
210
  * - 'objectIdGetter': `true` by default. Mongoose adds a getter to MongoDB ObjectId's called `_id` that returns `this` for convenience with populate. Set this to false to remove the getter.
package/lib/model.js CHANGED
@@ -1215,6 +1215,7 @@ Model.exists = function exists(filter, options, callback) {
1215
1215
  * @param {Boolean} [options.clone=true] By default, `discriminator()` clones the given `schema`. Set to `false` to skip cloning.
1216
1216
  * @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.
1217
1217
  * @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.
1218
+ * @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.
1218
1219
  * @return {Model} The newly created discriminator model
1219
1220
  * @api public
1220
1221
  */
@@ -1232,6 +1233,7 @@ Model.discriminator = function(name, schema, options) {
1232
1233
  options = options || {};
1233
1234
  const value = utils.isPOJO(options) ? options.value : options;
1234
1235
  const clone = typeof options.clone === 'boolean' ? options.clone : true;
1236
+ const mergePlugins = typeof options.mergePlugins === 'boolean' ? options.mergePlugins : true;
1235
1237
 
1236
1238
  _checkContext(this, 'discriminator');
1237
1239
 
@@ -1242,7 +1244,7 @@ Model.discriminator = function(name, schema, options) {
1242
1244
  schema = schema.clone();
1243
1245
  }
1244
1246
 
1245
- schema = discriminator(this, name, schema, value, true, options.mergeHooks);
1247
+ schema = discriminator(this, name, schema, value, mergePlugins, options.mergeHooks);
1246
1248
  if (this.db.models[name] && !schema.options.overwriteModels) {
1247
1249
  throw new OverwriteModelError(name);
1248
1250
  }
@@ -4554,7 +4556,7 @@ Model.validate = function validate(obj, pathsToValidate, context, callback) {
4554
4556
  * - match: optional query conditions to match
4555
4557
  * - model: optional name of the model to use for population
4556
4558
  * - options: optional query options like sort, limit, etc
4557
- * - justOne: optional boolean, if true Mongoose will always set `path` to an array. Inferred from schema by default.
4559
+ * - justOne: optional boolean, if true Mongoose will always set `path` to a document, or `null` if no document was found. If false, Mongoose will always set `path` to an array, which will be empty if no documents are found. Inferred from schema by default.
4558
4560
  * - strictPopulate: optional boolean, set to `false` to allow populating paths that aren't in the schema.
4559
4561
  *
4560
4562
  * #### Example:
package/lib/query.js CHANGED
@@ -4574,8 +4574,11 @@ Query.prototype.updateMany = function(conditions, doc, options, callback) {
4574
4574
  * #### Example:
4575
4575
  *
4576
4576
  * const res = await Person.updateOne({ name: 'Jean-Luc Picard' }, { ship: 'USS Enterprise' });
4577
- * res.n; // Number of documents matched
4578
- * res.nModified; // Number of documents modified
4577
+ * res.acknowledged; // Indicates if this write result was acknowledged. If not, then all other members of this result will be undefined.
4578
+ * res.matchedCount; // Number of documents that matched the filter
4579
+ * res.modifiedCount; // Number of documents that were modified
4580
+ * res.upsertedCount; // Number of documents that were upserted
4581
+ * res.upsertedId; // Identifier of the inserted document (if an upsert took place)
4579
4582
  *
4580
4583
  * This function triggers the following middleware.
4581
4584
  *
@@ -4638,8 +4641,11 @@ Query.prototype.updateOne = function(conditions, doc, options, callback) {
4638
4641
  * #### Example:
4639
4642
  *
4640
4643
  * const res = await Person.replaceOne({ _id: 24601 }, { name: 'Jean Valjean' });
4641
- * res.n; // Number of documents matched
4642
- * res.nModified; // Number of documents modified
4644
+ * res.acknowledged; // Indicates if this write result was acknowledged. If not, then all other members of this result will be undefined.
4645
+ * res.matchedCount; // Number of documents that matched the filter
4646
+ * res.modifiedCount; // Number of documents that were modified
4647
+ * res.upsertedCount; // Number of documents that were upserted
4648
+ * res.upsertedId; // Identifier of the inserted document (if an upsert took place)
4643
4649
  *
4644
4650
  * This function triggers the following middleware.
4645
4651
  *
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "6.7.1",
4
+ "version": "6.7.3",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -190,9 +190,6 @@ declare module 'mongoose' {
190
190
  /** Returns the list of paths that have been modified. */
191
191
  modifiedPaths(options?: { includeChildren?: boolean }): Array<string>;
192
192
 
193
- /** The name of the model */
194
- modelName: string;
195
-
196
193
  /**
197
194
  * Overwrite all values in this document with the values of `obj`, except
198
195
  * for immutable properties. Behaves similarly to `set()`, except for it
package/types/index.d.ts CHANGED
@@ -258,8 +258,8 @@ declare module 'mongoose' {
258
258
  obj: SchemaDefinition<SchemaDefinitionType<EnforcedDocType>>;
259
259
 
260
260
  /** Gets/sets schema paths. */
261
+ path<ResultType extends SchemaType = SchemaType<any, HydratedDocument<DocType, TInstanceMethods>>>(path: string): ResultType;
261
262
  path<pathGeneric extends keyof EnforcedDocType>(path: pathGeneric): SchemaType<EnforcedDocType[pathGeneric]>;
262
- path<ResultType extends SchemaType = SchemaType>(path: string): ResultType;
263
263
  path(path: string, constructor: any): this;
264
264
 
265
265
  /** Lists all paths and their type in the schema. */
@@ -274,19 +274,19 @@ declare module 'mongoose' {
274
274
  plugin<PFunc extends PluginFunction<DocType, M, any, any, any, any>, POptions extends Parameters<PFunc>[1] = Parameters<PFunc>[1]>(fn: PFunc, opts?: POptions): this;
275
275
 
276
276
  /** Defines a post hook for the model. */
277
- post<T = HydratedDocument<DocType, TInstanceMethods>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, fn: PostMiddlewareFunction<T, T>): this;
278
- post<T = HydratedDocument<DocType, TInstanceMethods>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, options: SchemaPostOptions, fn: PostMiddlewareFunction<T, T>): this;
279
277
  post<T = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | RegExp, fn: PostMiddlewareFunction<T, QueryResultType<T>>): this;
280
278
  post<T = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | RegExp, options: SchemaPostOptions, fn: PostMiddlewareFunction<T, QueryResultType<T>>): this;
279
+ post<T = HydratedDocument<DocType, TInstanceMethods>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, fn: PostMiddlewareFunction<T, T>): this;
280
+ post<T = HydratedDocument<DocType, TInstanceMethods>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, options: SchemaPostOptions, fn: PostMiddlewareFunction<T, T>): this;
281
281
  post<T extends Aggregate<any>>(method: 'aggregate' | RegExp, fn: PostMiddlewareFunction<T, Array<AggregateExtract<T>>>): this;
282
282
  post<T extends Aggregate<any>>(method: 'aggregate' | RegExp, options: SchemaPostOptions, fn: PostMiddlewareFunction<T, Array<AggregateExtract<T>>>): this;
283
283
  post<T = M>(method: 'insertMany' | RegExp, fn: PostMiddlewareFunction<T, T>): this;
284
284
  post<T = M>(method: 'insertMany' | RegExp, options: SchemaPostOptions, fn: PostMiddlewareFunction<T, T>): this;
285
285
 
286
- post<T = HydratedDocument<DocType, TInstanceMethods>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, fn: ErrorHandlingMiddlewareFunction<T>): this;
287
- post<T = HydratedDocument<DocType, TInstanceMethods>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, options: SchemaPostOptions, fn: ErrorHandlingMiddlewareFunction<T>): this;
288
286
  post<T = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | RegExp, fn: ErrorHandlingMiddlewareFunction<T>): this;
289
287
  post<T = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | RegExp, options: SchemaPostOptions, fn: ErrorHandlingMiddlewareFunction<T>): this;
288
+ post<T = HydratedDocument<DocType, TInstanceMethods>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, fn: ErrorHandlingMiddlewareFunction<T>): this;
289
+ post<T = HydratedDocument<DocType, TInstanceMethods>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, options: SchemaPostOptions, fn: ErrorHandlingMiddlewareFunction<T>): this;
290
290
  post<T extends Aggregate<any>>(method: 'aggregate' | RegExp, fn: ErrorHandlingMiddlewareFunction<T, Array<any>>): this;
291
291
  post<T extends Aggregate<any>>(method: 'aggregate' | RegExp, options: SchemaPostOptions, fn: ErrorHandlingMiddlewareFunction<T, Array<any>>): this;
292
292
  post<T = M>(method: 'insertMany' | RegExp, fn: ErrorHandlingMiddlewareFunction<T>): this;
@@ -295,10 +295,10 @@ declare module 'mongoose' {
295
295
  /** Defines a pre hook for the model. */
296
296
  pre<T = HydratedDocument<DocType, TInstanceMethods>>(method: 'save', fn: PreSaveMiddlewareFunction<T>): this;
297
297
  pre<T = HydratedDocument<DocType, TInstanceMethods>>(method: 'save', options: SchemaPreOptions, fn: PreSaveMiddlewareFunction<T>): this;
298
- pre<T = HydratedDocument<DocType, TInstanceMethods>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, fn: PreMiddlewareFunction<T>): this;
299
- pre<T = HydratedDocument<DocType, TInstanceMethods>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, options: SchemaPreOptions, fn: PreMiddlewareFunction<T>): this;
300
298
  pre<T = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | RegExp, fn: PreMiddlewareFunction<T>): this;
301
299
  pre<T = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | RegExp, options: SchemaPreOptions, fn: PreMiddlewareFunction<T>): this;
300
+ pre<T = HydratedDocument<DocType, TInstanceMethods>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, fn: PreMiddlewareFunction<T>): this;
301
+ pre<T = HydratedDocument<DocType, TInstanceMethods>>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, options: SchemaPreOptions, fn: PreMiddlewareFunction<T>): this;
302
302
  pre<T extends Aggregate<any>>(method: 'aggregate' | RegExp, fn: PreMiddlewareFunction<T>): this;
303
303
  pre<T extends Aggregate<any>>(method: 'aggregate' | RegExp, options: SchemaPreOptions, fn: PreMiddlewareFunction<T>): this;
304
304
  pre<T = M>(method: 'insertMany' | RegExp, fn: (this: T, next: (err?: CallbackError) => void, docs: any | Array<any>) => void | Promise<void>): this;
@@ -551,7 +551,6 @@ declare module 'mongoose' {
551
551
  export type SchemaDefinitionType<T> = T extends Document ? Omit<T, Exclude<keyof Document, '_id' | 'id' | '__v'>> : T;
552
552
 
553
553
  // Helpers to simplify checks
554
- type IfAny<IFTYPE, THENTYPE, ELSETYPE = IFTYPE> = 0 extends (1 & IFTYPE) ? THENTYPE : ELSETYPE;
555
554
  type IfUnknown<IFTYPE, THENTYPE> = unknown extends IFTYPE ? THENTYPE : IFTYPE;
556
555
 
557
556
  // tests for these two types are located in test/types/lean.test.ts
@@ -38,7 +38,7 @@ declare module 'mongoose' {
38
38
  * // result
39
39
  * type UserType = {userName?: string}
40
40
  */
41
- type InferSchemaType<TSchema> = ObtainSchemaGeneric<TSchema, 'DocType'>;
41
+ type InferSchemaType<TSchema> = IfAny<TSchema, any, ObtainSchemaGeneric<TSchema, 'DocType'>>;
42
42
 
43
43
  /**
44
44
  * @summary Obtains schema Generic type by using generic alias.
@@ -177,11 +177,13 @@ type ResolvePathType<PathValueType, Options extends SchemaTypeOptions<PathValueT
177
177
  PathValueType extends 'decimal128' | 'Decimal128' | typeof Schema.Types.Decimal128 ? Types.Decimal128 :
178
178
  IfEquals<PathValueType, Schema.Types.Decimal128> extends true ? Types.Decimal128 :
179
179
  IfEquals<PathValueType, Types.Decimal128> extends true ? Types.Decimal128 :
180
- PathValueType extends MapConstructor ? Map<string, ResolvePathType<Options['of']>> :
181
- PathValueType extends ArrayConstructor ? any[] :
182
- PathValueType extends typeof Schema.Types.Mixed ? any:
183
- IfEquals<PathValueType, ObjectConstructor> extends true ? any:
184
- IfEquals<PathValueType, {}> extends true ? any:
185
- PathValueType extends typeof SchemaType ? PathValueType['prototype'] :
186
- PathValueType extends Record<string, any> ? ObtainDocumentType<PathValueType, any, TypeKey> :
187
- unknown;
180
+ PathValueType extends 'uuid' | 'UUID' | typeof Schema.Types.UUID ? Buffer :
181
+ IfEquals<PathValueType, Schema.Types.UUID> extends true ? Buffer :
182
+ PathValueType extends MapConstructor ? Map<string, ResolvePathType<Options['of']>> :
183
+ PathValueType extends ArrayConstructor ? any[] :
184
+ PathValueType extends typeof Schema.Types.Mixed ? any:
185
+ IfEquals<PathValueType, ObjectConstructor> extends true ? any:
186
+ IfEquals<PathValueType, {}> extends true ? any:
187
+ PathValueType extends typeof SchemaType ? PathValueType['prototype'] :
188
+ PathValueType extends Record<string, any> ? ObtainDocumentType<PathValueType, any, TypeKey> :
189
+ unknown;
package/types/models.d.ts CHANGED
@@ -6,6 +6,7 @@ declare module 'mongoose' {
6
6
  clone?: boolean;
7
7
  overwriteModels?: boolean;
8
8
  mergeHooks?: boolean;
9
+ mergePlugins?: boolean;
9
10
  }
10
11
 
11
12
  export interface AcceptsDiscriminator {
@@ -213,7 +213,7 @@ declare module 'mongoose' {
213
213
 
214
214
  export interface ReplaceWith {
215
215
  /** [`$replaceWith` reference](https://docs.mongodb.com/manual/reference/operator/aggregation/replaceWith/) */
216
- $replaceWith: ObjectExpressionOperator | { [field: string]: Expression };
216
+ $replaceWith: ObjectExpressionOperator | { [field: string]: Expression } | `$${string}`;
217
217
  }
218
218
 
219
219
  export interface Sample {
@@ -26,8 +26,9 @@ declare module 'mongoose' {
26
26
  /** deep populate */
27
27
  populate?: string | PopulateOptions | (string | PopulateOptions)[];
28
28
  /**
29
- * If true Mongoose will always set `path` to an array, if false Mongoose will
30
- * always set `path` to a document. Inferred from schema by default.
29
+ * If true Mongoose will always set `path` to a document, or `null` if no document was found.
30
+ * If false Mongoose will always set `path` to an array, which will be empty if no documents are found.
31
+ * Inferred from schema by default.
31
32
  */
32
33
  justOne?: boolean;
33
34
  /** transform function to call on every populated doc */
@@ -100,7 +100,7 @@ declare module 'mongoose' {
100
100
  * If [truthy](https://masteringjs.io/tutorials/fundamentals/truthy), Mongoose will
101
101
  * build an index on this path when the model is compiled.
102
102
  */
103
- index?: boolean | IndexDirection;
103
+ index?: boolean | IndexDirection | IndexOptions;
104
104
 
105
105
  /**
106
106
  * If [truthy](https://masteringjs.io/tutorials/fundamentals/truthy), Mongoose
@@ -188,7 +188,11 @@ declare module 'mongoose' {
188
188
  [other: string]: any;
189
189
  }
190
190
 
191
- class SchemaType<T = any> {
191
+ interface Validator {
192
+ message?: string; type?: string; validator?: Function
193
+ }
194
+
195
+ class SchemaType<T = any, DocType = any> {
192
196
  /** SchemaType constructor */
193
197
  constructor(path: string, options?: AnyObject, instance?: string);
194
198
 
@@ -270,10 +274,10 @@ declare module 'mongoose' {
270
274
  unique(bool: boolean): this;
271
275
 
272
276
  /** The validators that Mongoose should run to validate properties at this SchemaType's path. */
273
- validators: { message?: string; type?: string; validator?: Function }[];
277
+ validators: Validator[];
274
278
 
275
279
  /** Adds validator(s) for this document path. */
276
- validate(obj: RegExp | Function | any, errorMsg?: string, type?: string): this;
280
+ validate(obj: RegExp | ((this: DocType, value: any, validatorProperties?: Validator) => any), errorMsg?: string, type?: string): this;
277
281
  }
278
282
 
279
283
  namespace Schema {
@@ -422,6 +426,11 @@ declare module 'mongoose' {
422
426
  /** Adds an uppercase [setter](http://mongoosejs.com/docs/api.html#schematype_SchemaType-set). */
423
427
  uppercase(shouldApply?: boolean): this;
424
428
  }
429
+
430
+ class UUID extends SchemaType {
431
+ /** This schema type's name, to defend against minifiers that mangle function names. */
432
+ static schemaName: 'UUID';
433
+ }
425
434
  }
426
435
  }
427
436
  }
@@ -1,4 +1,5 @@
1
1
  declare module 'mongoose' {
2
+ type IfAny<IFTYPE, THENTYPE, ELSETYPE = IFTYPE> = 0 extends (1 & IFTYPE) ? THENTYPE : ELSETYPE;
2
3
 
3
4
  type Unpacked<T> = T extends (infer U)[] ?
4
5
  U :